zoukankan      html  css  js  c++  java
  • 【Codeforces 1290】C Prefix Enlightenment(带权并查集)

    传送门

    ldxldx抓来看题
    然后还没看完ldxldx就切掉了把我喊去看DD
    结果还没看完就地震了

    首先任意三个集合交为空
    那么任意一个元素最多出现在两个集合内
    考虑把集合看做点,元素看做边
    那么实际上实际上就是给图黑白染色
    每个边要求两边同/异色
    用带权并查集维护同异色个数即可

    对于只出现在一个集合的元素特殊处理即可

    #include<bits/stdc++.h>
    using namespace std;
    #define re register
    #define cs const
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    #define bg begin
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    inline void readstring(char *s){
    	int top=0;char ch=gc();
    	while(isspace(ch))ch=gc();
    	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=600005;
    int n,k;
    ll ans;
    int fa[N],kd[N];
    ll same[N],dif[N];
    vector<int> lnk[N];
    inline pii find(int x){
    	if(x==fa[x])return pii(x,0);
    	pii now=find(fa[x]);
    	fa[x]=now.fi,kd[x]^=now.se;
    	return pii(fa[x],kd[x]);
    }
    inline void merge(int u,int v,int tp){
    	pii v1=find(u),v2=find(v);tp^=v1.se,tp^=v2.se;
    	int f1=v1.fi,f2=v2.fi;
    	if(f1==f2)return;
    	ans-=min(same[f1],dif[f1]),ans-=min(same[f2],dif[f2]);
    	if(tp)same[f1]+=dif[f2],dif[f1]+=same[f2],kd[f2]=1;
    	else same[f1]+=same[f2],dif[f1]+=dif[f2],kd[f2]=0;
    	ans+=min(same[f1],dif[f1]),fa[f2]=f1;
    }
    inline void calc(int u,int tp){
    	pii x=find(u);
    	ans-=min(same[x.fi],dif[x.fi]);
    	if(tp^x.se)dif[x.fi]+=1e9;
    	else same[x.fi]+=1e9;
    	ans+=min(same[x.fi],dif[x.fi]);
    }
    char a[N];
    signed main(){
    	#ifdef Stargazer
    	freopen("lx.in","r",stdin);
    	#endif
    	n=read(),k=read();
    	readstring(a);
    	for(int i=1;i<=k;i++){
    		fa[i]=i,same[i]=1,dif[i]=0,kd[i]=0;
    		int m=read();
    		while(m--)lnk[read()].pb(i);
    	}
    	for(int i=1;i<=n;i++){
    		if(lnk[i].size()==1) calc(lnk[i][0],a[i]=='0');
    		if(lnk[i].size()==2) merge(lnk[i][0],lnk[i][1],a[i]=='0');
    		cout<<ans<<'
    ';
    	}
    }
    
    
  • 相关阅读:
    cf1270D——交互,思维
    cf1270E —— 奇偶构造!+ 坐标系分类讨论旋转
    cf1207E——交互,思维
    cf1271D——经典 dp+贪心+图论
    cf1271E——数学找规律,二分套二分
    cf1272E——bfs反边图
    cf1272F——经典升维dp,好题!
    cf1276B——割点+深搜树
    cf1276C——单调性分析,思维
    cf1277D——思维贪心+字符串
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328315.html
Copyright © 2011-2022 走看看