3514: Codechef MARCH14 GERALD07加强版
Time Limit: 60 Sec Memory Limit: 256 MB
Submit: 2177 Solved: 834
[Submit][Status][Discuss]Description
N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。
Input
第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
接下来M行,代表图中的每条边。
接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。Output
K行每行一个整数代表该组询问的联通块个数。
Sample Input
3 5 4 0
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
Sample Output
2
1
3
1
HINT
对于100%的数据,1≤N、M、K≤200,000。
2016.2.26提高时限至60s
Source
用LCT求出NTR数组,然后主席树在线查询即可,比较简洁巧妙。
不过是两个高级数据结构合在一起,而且不是嵌套,理论上很好写。
实际上犯了很多低级错误,而且非常难调,以后一定要慢点写代码。
1 #include<cstdio> 2 #include<algorithm> 3 #define lc ch[x][0] 4 #define rc ch[x][1] 5 #define rep(i,l,r) for (int i=l; i<=r; i++) 6 using namespace std; 7 8 const int N=400100,K=200100,M=4000100,inf=1000000000; 9 int n,m,Q,op,l,r,x,u,v,nd,ans,fa[N],ntr[K],root[K]; 10 struct E{ int u,v; }e[K]; 11 int find(int x){ return (fa[x]==x) ? x : fa[x]=find(fa[x]); } 12 13 struct LCT{ 14 int v[N],mn[N],s[N],ch[N][2],f[N],tag[N]; 15 bool isroot(int x){ return (!f[x]) || ((ch[f[x]][0]!=x) && (ch[f[x]][1]!=x)); } 16 void rev(int x){ swap(ch[x][0],ch[x][1]); tag[x]^=1; } 17 void push(int x){ if (tag[x]) rev(lc),rev(rc),tag[x]=0; } 18 void pd(int x){ if (!isroot(x)) pd(f[x]); push(x); } 19 20 void upd(int x){ 21 mn[x]=x; 22 if (v[mn[lc]]<v[mn[x]]) mn[x]=mn[lc]; 23 if (v[mn[rc]]<v[mn[x]]) mn[x]=mn[rc]; 24 } 25 26 void rot(int x){ 27 int y=f[x],z=f[y],w=ch[y][1]==x; 28 if (!isroot(y)) ch[z][ch[z][1]==y]=x; 29 f[x]=z; f[y]=x; f[ch[x][w^1]]=y; 30 ch[y][w]=ch[x][w^1]; ch[x][w^1]=y; upd(y); 31 } 32 33 void splay(int x){ 34 pd(x); 35 while (!isroot(x)){ 36 int y=f[x],z=f[y]; 37 if (!isroot(y)){ if ((ch[z][0]==y)^(ch[y][0]==x)) rot(x); else rot(y); } 38 rot(x); 39 } 40 upd(x); 41 } 42 43 void access(int x){ for (int y=0; x; y=x,x=f[x]) splay(x),ch[x][1]=y,upd(x); } 44 void mkroot(int x){ access(x); splay(x); rev(x);} 45 void link(int x,int y){ mkroot(x); f[x]=y; } 46 void cut(int x,int y){ mkroot(x); access(y); splay(y); ch[y][0]=f[x]=0; upd(y); } 47 int que(int x,int y){ mkroot(x); access(y); splay(y); return mn[y]; } 48 }T; 49 50 struct S{ 51 int ls[M],rs[M],sm[M]; 52 53 void ins(int y,int &x,int L,int R,int pos){ 54 x=++nd; ls[x]=ls[y]; rs[x]=rs[y]; sm[x]=sm[y]+1; 55 if (L==R) return; int mid=(L+R)>>1; 56 if (pos<=mid) ins(ls[y],ls[x],L,mid,pos); else ins(rs[y],rs[x],mid+1,R,pos); 57 } 58 59 int que(int x,int y,int L,int R,int k){ 60 if (R==k){ return sm[y]-sm[x]; } 61 int mid=(L+R)>>1; 62 if (k<=mid) return que(ls[x],ls[y],L,mid,k); 63 else return sm[ls[y]]-sm[ls[x]]+que(rs[x],rs[y],mid+1,R,k); 64 } 65 }S; 66 67 void Kruskal(){ 68 int tot=n; 69 rep(i,1,n) fa[i]=i; 70 rep(i,1,m){ 71 int u=e[i].u,v=e[i].v,x=find(u),y=find(v); 72 if (u==v) { ntr[i]=i; continue; } 73 if (x==y){ 74 int t=T.que(u,v),k=T.v[t]; 75 ntr[i]=k; T.cut(e[k].u,t); T.cut(e[k].v,t); 76 }else fa[x]=y; 77 tot++; T.mn[tot]=tot; T.v[tot]=i; 78 T.link(u,tot); T.link(v,tot); 79 } 80 rep(i,1,m) S.ins(root[i-1],root[i],0,m,ntr[i]); 81 } 82 83 void solve(){ 84 rep(i,1,Q){ 85 scanf("%d%d",&l,&r); 86 if (op) l^=ans,r^=ans; 87 printf("%d\n",ans=n-S.que(root[l-1],root[r],0,m,l-1)); 88 } 89 } 90 91 int main(){ 92 freopen("bzoj3514.in","r",stdin); 93 freopen("bzoj3514.out","w",stdout); 94 scanf("%d%d%d%d",&n,&m,&Q,&op); 95 T.v[0]=inf; rep(i,1,n) T.mn[i]=i,T.v[i]=inf; 96 rep(i,1,m) scanf("%d%d",&e[i].u,&e[i].v); 97 Kruskal(); solve(); 98 return 0; 99 }
b
原文地址:https://www.cnblogs.com/HocRiser/p/8552656.html
时间: 2024-10-05 05:11:57