Codeforces Round #819 (Div. 1 + Div. 2)

B. Mainak and Interesting Sequence

思路:要想存在构造方法,则数组a中除了最大数外的其它数出现次数都必须是偶数

证明:假设数x出现了奇数次,令y为数组中恰好比x大的数,即y>x且不存在t,使得y>t>x,因为x不是最大数,因此这样的y一定存在。令P(y)为数组中小于y的所有数的异或值,则有题意可知P(y)=0,又因为0=P(y)=P(x)⊕x=0⊕x=x且x>0,因此矛盾,所以x必须出现偶数次

证完后就很容易构造答案了

代码:

void slove(){
   int n,m;
   cin>>n>>m;
   if(n>m){
    cout << "NO" << endl;
    return;
   }
   if(n&1){
    cout << "YES" << endl;
    _for(i,0,n-1)cout << 1 << " ";
    cout << m-n+1 << endl;
   }
   else{
    if(m&1)cout << "NO" << endl;
    else{
        cout << "YES" << endl;
        _for(i,0,n-2)cout << 1 << " ";
        int tem=(m-n+2)/2;
        cout << tem << " " << tem << endl;
    }
   }
}

D. Edge Split

思路: 如果不成环的话,那么每条边都会使连通分量数减去一,所以我们的目标是不让构造出的两个图里出现环.

首先我们构造出任意一个生成树把生成树边全部染成红色,然后最多剩下三条边,如果这些边没有成环直接输出答案即可.

如果成环,我们就把剩下的边里任选一条染成红色,其它保持蓝色,但是这样红色的图里就会有环了,我们还要删除红色图中的环.我们可以选择刚才这条边的任意一个端点,把与这个端点有关的所有边染成蓝色(除了环上刚被染成红色的边).因为题目确认没有重边,所以染成蓝色的边一定不会生成新环.

其实只有恰好m=n+2的时候才会出现环

代码:

const int N = 200010;

int p[N];

int find(int x){
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}

void slove(){
   int n,m;
   cin>>n>>m;
   _fore(i,1,n)p[i]=i;
   int cnt[n+1];
   mm(cnt,0);
   int res[m];
   mm(res,0);
   vector<pair<int,int>> v;
   vector<int> vv;
   _for(i,0,m){
    int a,b;
    cin>>a>>b;
    v.pb({a,b});
    if(find(a)!=find(b)){
        p[find(a)]=find(b);
        res[i]=1;
    }
    else{
        cnt[a]++,cnt[b]++;
        vv.pb(i);
    }
   }
   int sum=0;
   _fore(i,1,n){
    if(cnt[i]==2)sum++;
   }
   if(sum==3){
    int tem=vv[0];
    res[tem]=1;
    int a=v[tem].first;
    _for(i,0,m){
        if(i==tem)continue;
        if(v[i].first==a||v[i].second==a){
            res[i]=0;
        }
    }
   }
   _for(i,0,m)cout << res[i];
   cout << endl;
}
end

Comments

留言