AtCoder Beginner Contest 396 (E-F)

后面补G

E-Min of Restricted Sum

当一个点值确定时,整个联通块的值也确定了,由此可以判断是否有解

同理,对于一个联通块内的根节点,其点值的二进制下的每位就独立的决定了其它点在该位的值,也就是说,若根节点值在一个二进制位下为0,可以决定其它点值在当前位下是0还是1,而若根节点在该位是1,则其他点值在该位就要取反

思路

对于一个连通块的根节点,先假设该点的值为0
dfs判断一下连通块是否合法,如合法,再统计连通块内其他点在每一位上的10的个数
1的个数大于0的个数,为了使得对答案的值更小,我们选择根节点的值在当前二进制位下为1,否则为0

const int N=2e5+5;
vector<pii>e[N];
int val[N],vis[N],ans[N];
vector<int>nw;
void dfs(int u){
    vis[u]=1;
    nw.push_back(u);
    for(auto [v,w]:e[u]){
        if(vis[v]){
            if((val[u]^w)!=val[v]){
                cout<<"-1";
                exit(0);
            }
        }
        else{
            val[v]=val[u]^w;
            dfs(v);
        }
    }
}
void solve(){
    int n,m;cin>>n>>m;
    rep(i,1,m){
        int u,v,w;cin>>u>>v>>w;
        e[u].push_back({v,w});
        e[v].push_back({u,w});
    }
    rep(i,1,n){
        if(vis[i]) continue;
        dfs(i);
        int tmp=0;
        rep(j,0,30){
            int cnt0=0,cnt1=0;
            for(auto u:nw){
                if(val[u]>>j&1) cnt1++;
                else cnt0++;
            }
            if(cnt1>cnt0) tmp|=1<<j;
        }
        ans[i]=tmp;
        for(auto u:nw) ans[u]=tmp^val[u];
        nw.clear();
    }
    _db(ans,n);
}

F - Rotated Inversions (atcoder.jp)

依旧是贡献法

思路

注意到每次只有值为m-1的数会影响答案

同时由m-1变为0对答案的影响是固定的

于是对每个数,可以预处理出它成为m-1时对答案的影响

代码实现

vector<pii>e[N];
int val[N],vis[N],ans[N];
vector<int>nw;
void dfs(int u){
    vis[u]=1;
    nw.push_back(u);
    for(auto [v,w]:e[u]){
        if(vis[v]){
            if((val[u]^w)!=val[v]){
                cout<<"-1";
                exit(0);
            }
        }
        else{
            val[v]=val[u]^w;
            dfs(v);
        }
    }
}
void solve(){
    int n,m;cin>>n>>m;
    rep(i,1,m){
        int u,v,w;cin>>u>>v>>w;
        e[u].push_back({v,w});
        e[v].push_back({u,w});
    }
    rep(i,1,n){
        if(vis[i]) continue;
        dfs(i);
        int tmp=0;
        rep(j,0,30){
            int cnt0=0,cnt1=0;
            for(auto u:nw){
                if(val[u]>>j&1) cnt1++;
                else cnt0++;
            }
            if(cnt1>cnt0) tmp|=1<<j;
        }
        ans[i]=tmp;
        for(auto u:nw) ans[u]=tmp^val[u];
        nw.clear();
    }
    _db(ans,n);
}
posted @ 2025-03-11 11:12  mono_4  阅读(80)  评论(0)    收藏  举报