topcoder srm 695 div1 -3

1、称一个串的子串(连续一段)为$same$当且仅当这个子串所有字符都一样。子串不同当且仅当在原串中的起始位置不同。现在构造一个长度为$n$的只包含字符'a','b'的串$s$,使得$s$满足长度为$L$ 的$same$子串恰有$x_{L}$个.有多个答案,输出字典序最小的。

思路:首先一个长度为4的$same$子串同样可以贡献出2个长度为3的,3个长度为2的等。所以可以先进行抵消。最后就是把各个部分拼起来。至于字典序最小,就是先放长的a,再放段的b ,交替进行。

#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <set>
#include <vector>
#include <time.h>
#include <queue>
#include <stack>
#include <map>
#include <assert.h>
using namespace std;



const int N=500005;



class BearPasswordLexic
{
public:

    string get(int x,int t)
    {
        string ans="";
        for(int i=1;i<=x;++i)
        {
            if(t==0) ans+='a';
            else ans+='b';
        }
        return ans;
    }

    string findPassword(vector <int> x)
    {
        vector<int> a;

        const int n=(int)x.size();
        for(int i=n-1;i>=0;--i) if(x[i])
        {
            if(x[i]<0) return "";

            for(int j=0;j<x[i];++j) a.push_back(i+1);
            for(int j=i;j>=1;--j)
            {
                x[j-1]-=(i+2-j)*x[i];
            }

        }
        sort(a.begin(),a.end());
        int i=0,j=a.size()-1;
        string ans="";
        while(i<j)
        {
            ans+=get(a[j],0);
            ans+=get(a[i],1);
            --j;
            ++i;
        }
        if(i==j) ans+=get(a[i],0);
        if(ans.size()!=n) return "";
        return ans;
    }
};

  

2、一个$n$个 顶点$m$条边的简单图,每个节点的度数最多为3。每个顶点有个权值$x_{v}$。现在对$K$条边进行更新。称一个顶点被更新当且仅当跟这个顶点相连的边中至少有一条被更新过。适当地选出$K$ 条边进行更新使得最后的被更新的顶点的权值和最大。

思路:首先,将边按照其两端顶点的权值和进行降序排序。现在,假设$K=1$,那么排序后的第一条边就是要选出的边;假设$K=2$,那么要选出的两条边一定在排序后的前六条边中。因为选出的第一条边最多影响额外的四条边,所以如果选择了第一条,那么最差的情况是影响了第2,3,4,5 条,所以第六条比之后的都要更优秀,所以不会选择后面的所有边中的边;假设第一条没有影响2,3,4,5中的,那么第二条选那条没有影响的就可以。类似$K=3$,答案一定在前十一条边中。依次类推,只需要考虑前$5(K-1)+1$条边即可。

#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <set>
#include <vector>
#include <time.h>
#include <queue>
#include <stack>
#include <map>
#include <assert.h>
using namespace std;



const int N=1005;


class BearKRoads
{
    vector<pair<int,pair<int,int> > > E;
    int n,m;
    int w[N];
    int ans;
    int h[N];

    void dfs(int dep,int cur,int Max,int val)
    {
        if(val>ans) ans=val;
        if(dep==0) return;
        if(cur>=Max) return;

        for(int i=cur;i<Max;++i)
        {
            int u=E[i].second.first;
            int v=E[i].second.second;
            int tmp=val;
            if(!h[u]) tmp+=w[u];
            if(!h[v]) tmp+=w[v];
            ++h[u];
            ++h[v];
            dfs(dep-1,i+1,Max,tmp);
            --h[u];
            --h[v];
        }

    }

public:
    int maxHappy(vector<int> x,vector<int> a,vector<int> b,int K)
    {
        n=(int)x.size();
        m=(int)a.size();
        for(int i=0;i<n;++i) w[i]=x[i];
        for(int i=0;i<m;++i)
        {
            int u=a[i],v=b[i];
            E.push_back(make_pair(w[u]+w[v],make_pair(u,v)));
        }
        sort(E.begin(),E.end());
        reverse(E.begin(),E.end());
        const int M=min(5*(K-1)+1,m);
        ans=0;
        memset(h,0,sizeof(h));
        dfs(K,0,M,0);
        return ans;
    }
};

  

原文地址:https://www.cnblogs.com/jianglangcaijin/p/6884315.html