loj 121 「离线可过」动态图连通性
这是一道被离线爆艹的模板题。
你要维护一张无向简单图。你被要求加入删除一条边及查询两个点是否连通。
0
:加入一条边。保证它不存在。1
:删除一条边。保证它存在。2
:查询两个点是否联通。
本题解法:
1.lct
2.对操作进行分块,然后维护并查集(需要回到过去)。 时间复杂度$O(m*sqrt(m)*logn)$
由于时限只有800ms,时间复杂度比较高,我优化了半天,也只能有93分。
1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int const N=5000+10; 5 int const M=500000+10; 6 int const B=1000; 7 #define st(x) (((x)-1)*B+1) 8 #define ed(x) min(m,(x)*B) 9 #define bl(x) (((x)-1)/B+1) 10 #define pii pair<int,int> 11 #define mp make_pair 12 #define Find(x) { while (x!=f[x]) x=f[x]; } 13 int n,m,f[N],s[N],x[M],y[M],z[M],st[N],top; 14 set<pii> mat,mt,se; 15 set<pii> :: iterator p; 16 char gc() 17 { 18 static char buf[100000000],*p1=buf,*p2=buf; 19 return p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++; 20 } 21 template<typename __Type_of__scan> 22 void read(__Type_of__scan &x) 23 { 24 __Type_of__scan f=1;x=0;char s=gc(); 25 while(s<'0'||s>'9'){if(s=='-')f=-1;s=gc();} 26 while(s>='0'&&s<='9'){x=x*10+s-'0';s=gc();} 27 x*=f; 28 } 29 int main(){ 30 freopen("graph6.in","r",stdin); 31 freopen("std.out","w",stdout); 32 read(n); read(m); 33 int tot=bl(m); 34 for(int i=1;i<=tot;i++){ 35 int beg=st(i),end=ed(i); 36 se.clear(); mt.clear(); 37 int cnt=0; 38 for(register int j=beg;j<=end;j++){ 39 read(z[j]);read(x[j]); read(y[j]); 40 if(z[j]==2){ 41 cnt++; continue; 42 } 43 if(x[j]>y[j]) swap(x[j],y[j]); 44 se.insert(mp(x[j],y[j])); 45 } 46 for(register int j=1;j<=n;j++) f[j]=j,s[j]=1; 47 if(i>1){ 48 int bb=st(i-1),ee=ed(i-1); 49 for(register int j=bb;j<=ee;j++) { 50 if(z[j]==2) continue; 51 if(mat.find(mp(x[j],y[j]))!=mat.end()) 52 mat.erase(mp(x[j],y[j])); 53 else 54 mat.insert(mp(x[j],y[j])); 55 } 56 } 57 if(cnt==0) continue; 58 for(p=mat.begin();p!=mat.end();p++){ 59 if(se.find(*p)!=se.end()) { 60 mt.insert(*p); 61 continue; 62 } 63 int fx=p->first; 64 int fy=p->second; 65 Find(fx);Find(fy); 66 if(fx!=fy){ 67 if(s[fx]>s[fy]) swap(fx,fy); 68 f[fx]=fy; 69 s[fy]+=s[fx]; 70 } 71 } 72 top=0; 73 for(register int j=beg;j<=end;j++){ 74 if(z[j]<2){ 75 if(mt.find(mp(x[j],y[j]))==mt.end()) 76 mt.insert(mp(x[j],y[j])); 77 else 78 mt.erase(mp(x[j],y[j])); 79 }else { 80 for( p=mt.begin();p!=mt.end();p++){ 81 int fx=p->first; 82 int fy=p->second; 83 Find(fx);Find(fy); 84 if(fx!=fy){ 85 if(s[fx]>s[fy]) swap(fx,fy); 86 f[fx]=fy; 87 s[fy]+=s[fx]; 88 st[++top]=fx; 89 } 90 } 91 int fx=x[j]; 92 int fy=y[j]; 93 Find(fx);Find(fy); 94 puts(fx==fy? "Y":"N"); 95 while (top) { 96 int t=st[top]; 97 s[f[t]]-=s[t]; 98 f[t]=t; 99 top--; 100 } 101 } 102 } 103 } 104 return 0; 105 }
3.线段树分治+ 并查集 时间复杂度$O(m*logm*logm) $
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=5000+10; 4 int const M=500000+10; 5 #define pii pair<int,int> 6 #define mid (l+r)/2 7 #define lc (x<<1) 8 #define rc (x<<1|1) 9 int n,m,f[N],s[N],st[N],tp,ans[M]; 10 pii q[M]; 11 map<pii,int> mp; 12 map<pii,int> :: iterator it; 13 vector<pii> v[M*4]; 14 int find(int x){ 15 return x==f[x]? x: find(f[x]); 16 } 17 void merge(int x,int y){ 18 x=find(x); y=find(y); 19 if(x==y) return; 20 if(s[x]>s[y]) swap(x,y); 21 f[x]=y; s[y]+=s[x]; st[++tp]=x; 22 } 23 24 void change(int x,int l,int r,int ll,int rr,pii d){ 25 if(ll<=l && r<=rr){ 26 v[x].push_back(d); return; 27 } 28 if(ll<=mid) change(lc,l,mid,ll,rr,d); 29 if(rr>mid) change(rc,mid+1,r,ll,rr,d); 30 } 31 void link(int x,int y,int ti){ 32 if(x>y) swap(x,y); 33 mp[make_pair(x,y)]=ti; 34 } 35 void cut(int x,int y,int ti){ 36 if(x>y) swap(x,y); 37 pii p=make_pair(x,y); 38 change(1,1,m,mp[p],ti-1,p); 39 mp[p]=0; 40 } 41 void undo(int t){ 42 while (tp>t){ 43 int x=st[tp--]; 44 s[f[x]]-=s[x]; 45 f[x]=x; 46 } 47 } 48 49 void solve(int x,int l,int r){ 50 int tp1=tp; 51 for(int i=0;i<v[x].size();i++) { 52 int xx=v[x][i].first,yy=v[x][i].second; 53 merge(xx,yy); 54 } 55 if(l==r){ 56 if(q[l].first) ans[l]=find(q[l].first)==find(q[l].second); 57 undo(tp1); return; 58 } 59 solve(lc,l,mid); 60 solve(rc,mid+1,r); 61 undo(tp1); 62 } 63 64 65 int main(){ 66 scanf("%d%d",&n,&m); 67 for(int i=1;i<=n;i++) f[i]=i,s[i]=1; 68 for(int i=1;i<=m;i++){ 69 int op,x,y; 70 scanf("%d%d%d",&op,&x,&y); 71 if(op==0) link(x,y,i); 72 else if(op==1) cut(x,y,i); 73 else q[i]=make_pair(x,y); 74 } 75 for(it=mp.begin();it!=mp.end();it++){ 76 if((*it).second!=0) { 77 pii p=(*it).first; 78 cut(p.first,p.second,m+1); 79 } 80 } 81 solve(1,1,m); 82 for(int i=1;i<=m;i++) if(q[i].first) 83 puts(ans[i]? "Y":"N"); 84 return 0; 85 }