n<=100000条相等/不等关系描述<=100000个数,把这些数据分割成若干段使得每一段描述都出现冲突且冲突只出现在最后一行。
相等关系具有传递性,并查集维护;不等关系根据相等关系进行合并,采用平衡树的启发式合并。
每次遇到相等关系x,y,先找到x,y对应并查集的根p,q,判是否p在q的不等关系中,若否说明成立,这时应合并并查集,并合并两棵平衡树,小的合到大的上。
每次遇到不等关系x,y,先找到x,y对应并查集的根p,q,判是否p和q在同一个并查集中,若否说明成立,这时应把p和q分别添加到对方的平衡树中。
平衡树调用set即可。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<set> 7 //#include<iostream> 8 using namespace std; 9 10 int T,n=200001; 11 #define maxn 200011 12 set<int> s[maxn]; 13 int cnt,vis[maxn],sta[maxn],top; 14 struct UFS 15 { 16 int fa[maxn]; 17 UFS() {for (int i=1;i<=n;i++) fa[i]=i;} 18 int find(int x) {return x==fa[x]?x:(fa[x]=find(fa[x]));} 19 void Union(int &x,int &y) 20 { 21 x=find(x),y=find(y); 22 if (x!=y) fa[x]=y; 23 } 24 }ufs; 25 int x,y,id; 26 int ans[maxn],lans=0,Case; 27 void clear() 28 { 29 while (top) 30 { 31 int now=sta[top--]; 32 ufs.fa[now]=now; 33 s[now].clear(); 34 } 35 ans[cnt++]=Case; 36 } 37 int main() 38 { 39 scanf("%d",&T); 40 memset(vis,0,sizeof(vis)); 41 top=0;cnt=1; 42 for (Case=1;Case<=T;Case++) 43 { 44 scanf("%d%d%d",&x,&y,&id); 45 if (vis[x]!=cnt) vis[x]=cnt,sta[++top]=x; 46 if (vis[y]!=cnt) vis[y]=cnt,sta[++top]=y; 47 x=ufs.find(x),y=ufs.find(y); 48 if (s[x].size()>s[y].size()) {int t=x;x=y;y=t;} 49 if (id) 50 { 51 if (s[x].find(y)!=s[x].end()) 52 { 53 clear(); 54 continue; 55 } 56 ufs.Union(x,y); 57 for (set<int>::iterator i=s[x].begin();i!=s[x].end();i++) 58 { 59 int now=*i;now=ufs.find(now); 60 s[now].erase(x); 61 s[y].insert(now); 62 s[now].insert(y); 63 } 64 s[x].clear(); 65 } 66 else 67 { 68 if (x==y) 69 { 70 clear(); 71 continue; 72 } 73 s[x].insert(y); 74 s[y].insert(x); 75 } 76 } 77 printf("%d\n",cnt-1); 78 for (int i=1;i<cnt;i++) printf("%d\n",ans[i]-ans[i-1]); 79 return 0; 80 }
时间: 2024-10-12 13:01:31