AtCoder Beginner Contest 396 (E-F)
后面补G
E-Min of Restricted Sum
当一个点值确定时,整个联通块的值也确定了,由此可以判断是否有解
同理,对于一个联通块内的根节点,其点值的二进制下的每位就独立的决定了其它点在该位的值,也就是说,若根节点值在一个二进制位下为
0,可以决定其它点值在当前位下是0还是1,而若根节点在该位是1,则其他点值在该位就要取反
思路
对于一个连通块的根节点,先假设该点的值为0
dfs判断一下连通块是否合法,如合法,再统计连通块内其他点在每一位上的1与0的个数
若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);
}

浙公网安备 33010602011771号