先线段树分治,但事实上与普通的动态连通性/二分图的判定有很大的区别:
1.对每一个修改(建议将初始的边也作为无色修改),在其第一次修改时进行判定,若发现不合法则将其颜色改为对该边最后一次可行的修改,之后再执行即可;
2.操作顺序会影响,有可能左子树中的操作先于父亲的操作
对于此类操作,必然要求父亲之前未被操作(否则没有影响),换言之其左端点恰好为区间左端点
注意到由于左端点各不相同,因此比其早的操作一定恰好是他的一条左链(左儿子、左儿子的左儿子……)上的所有操作
具体实现可以记录当前那个不确定是否执行的操作(根据左端点各不相同,是唯一的),在搜索到叶子时再判断,当左儿子返回合法后再执行(注意每一个左儿子返回都要执行)
时间复杂度为$o(nlog^{2}n+nk)$($n$、$m$、$q$同阶,两个log分别是线段树分治和并查集,$nk$是初始化并查集),可以通过
(代码有点问题,拍不出来懒得查了,思路yy的感觉没啥问题)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 struct ji{ 8 int id,c; 9 }u[N<<1]; 10 vector<int>v[N<<3]; 11 int n,m,q,un,x[N],y[N],las[N],ans[N<<1]; 12 void update(int k,int l,int r,int x,int y,int z){ 13 if ((l>y)||(x>r))return; 14 if ((x<=l)&&(r<=y)){ 15 v[k].push_back(z); 16 return; 17 } 18 update(L,l,mid,x,y,z); 19 update(R,mid+1,r,x,y,z); 20 } 21 struct union_find{ 22 int len[N],d[N],sz[N],f[N]; 23 vector<int>v; 24 void init(){ 25 for(int i=1;i<=n;i++){ 26 f[i]=i; 27 sz[i]=1; 28 } 29 } 30 int find(int k){ 31 if (k==f[k]){ 32 d[k]=0; 33 return k; 34 } 35 int fa=find(f[k]); 36 d[k]=(d[f[k]]^len[k]); 37 return fa; 38 } 39 bool add(int x,int y){//0表示产生奇环 40 if (find(x)==find(y))return d[x]^d[y]; 41 int p=(d[x]^d[y]); 42 x=find(x),y=find(y); 43 if (sz[x]<sz[y])swap(x,y); 44 v.push_back(y); 45 f[y]=x; 46 len[y]=(p^1); 47 sz[x]+=sz[y]; 48 return 1; 49 } 50 void ctrlz(int now){ 51 while (v.size()>now){ 52 int k=v.back(); 53 v.pop_back(); 54 sz[f[k]]-=sz[k]; 55 len[k]=0; 56 f[k]=k; 57 } 58 } 59 }T[51]; 60 bool check(int k){ 61 int id=u[k].id; 62 ans[k]=T[u[k].c].add(x[id],y[id]); 63 if (!u[k].c)ans[k]=1; 64 if (!ans[k])u[k].c=las[id]; 65 return ans[k]; 66 } 67 void add(int k){ 68 int id=u[k].id; 69 T[u[k].c].add(x[id],y[id]); 70 las[id]=u[k].c; 71 } 72 bool dfs(int k,int l,int r,int un){ 73 int flag=0,now[51]; 74 for(int i=0;i<=50;i++)now[i]=T[i].v.size(); 75 for(int i=0;i<v[k].size();i++) 76 if (ans[v[k][i]]>=0)add(v[k][i]); 77 else un=v[k][i]; 78 if (l==r){ 79 if (un)flag=check(un); 80 } 81 else{ 82 flag=dfs(L,l,mid,un); 83 if (flag)add(un); 84 dfs(R,mid+1,r,0); 85 } 86 for(int i=0;i<=50;i++)T[i].ctrlz(now[i]); 87 return flag; 88 } 89 int main(){ 90 scanf("%d%d%*d%d",&n,&m,&q); 91 for(int i=1;i<=m;i++){ 92 scanf("%d%d",&x[i],&y[i]); 93 u[i].id=las[i]=i; 94 } 95 for(int i=m+1;i<=q+m;i++){ 96 scanf("%d%d",&u[i].id,&u[i].c); 97 update(1,1,m+q,las[u[i].id],i-1,las[u[i].id]); 98 las[u[i].id]=i; 99 } 100 for(int i=1;i<=m;i++)update(1,1,m+q,las[i],m+q,las[i]); 101 memset(las,0,sizeof(las)); 102 memset(ans,-1,sizeof(ans)); 103 for(int i=1;i<=m;i++)ans[i]=1; 104 for(int i=0;i<=50;i++)T[i].init(); 105 dfs(1,1,m+q,0); 106 for(int i=m+1;i<=m+q;i++) 107 if (ans[i])printf("YES "); 108 else printf("NO "); 109 return 0; 110 }