3514: Codechef MARCH14 GERALD07加强版
Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2395 Solved: 922
[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
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
Sample Output
2
1
3
1
1
3
1
HINT
对于100%的数据,1≤N、M、K≤200,000。
2016.2.26提高时限至60s
Source
题意:无向图,维护边的编号在[l,r]的边形成的点连通块个数;
题解: 一般有一下一些情况:
① 无向图,维护边的编号在[l,r]的点连通块个数
②无向图,维护点的编号在[l,r]的生成子图连通块个数;
③强制在线??
题解:好神
①将边按照编号不断加入LCT,如果没有形成环就直接加入,如果形成了一个环就删去环上编号最小的边,这样LCT里面会保留尽量靠后的边,将询问按右端点排序,答案是n - LCT里面编号在[l,r]的数目;
可以用树状数组维护边编号;
②将点看成一个序列,将边(u,v)看成一条线段并按右端点排序,按照一样的方法不断加入边,只是这次有环就删去左端点编号最小的值,答案同样是[r-l+1]-LCT里面左端点编号在[l,r]的数目;
也可以用树状数组维护;
③离线太白痴了,树状数组换成主席树就可以了,LCT维护边的信息时将边看成一个点;
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #include<cmath> 7 #include<vector> 8 #include<stack> 9 #include<map> 10 #define Run(i,l,r) for(int i=l;i<=r;i++) 11 #define Don(i,l,r) for(int i=l;i>=r;i--) 12 #define ll long long 13 #define inf 0x3f3f3f3f 14 using namespace std; 15 const int N=200010; 16 int n,m,q,sz,typ,rt[N],ls[N*40],rs[N*40],sum[N*40]; 17 int ch[N<<1][2],fa[N<<1],mn[N<<1],val[N<<1],rev[N<<1]; 18 struct edge{int u,v;}e[N]; 19 char gc(){ 20 static char*p1,*p2,s[1000000]; 21 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 22 return(p1==p2)?EOF:*p1++; 23 }// 24 int rd(){ 25 int x=0; char c=gc(); 26 while(c<'0'||c>'9')c=gc(); 27 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); 28 return x; 29 }// 30 bool is_rt(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}// 31 void pushup(int x){mn[x]=min(val[x],min(mn[ch[x][0]],mn[ch[x][1]]));}// 32 void pushdown(int x){ 33 if(rev[x]){ 34 swap(ch[x][0],ch[x][1]); 35 rev[ch[x][0]]^=1; 36 rev[ch[x][1]]^=1; 37 rev[x]^=1; 38 } 39 }// 40 void rotate(int x){ 41 int y=fa[x] , z=fa[y]; 42 if(!is_rt(y))ch[z][ch[z][1]==y]=x; 43 int l=ch[y][1]==x,r=l^1; 44 fa[y]=x;fa[x]=z;fa[ch[x][r]]=y; 45 ch[y][l]=ch[x][r];ch[x][r]=y; 46 pushup(y),pushup(x); 47 }// 48 void push(int x){ 49 if(!is_rt(x))push(fa[x]); 50 pushdown(x); 51 }// 52 void splay(int x){ 53 push(x); 54 for(int y,z;!is_rt(x);rotate(x)){ 55 y=fa[x],z=fa[y]; 56 if(!is_rt(y))rotate((ch[z][1]==y)^(ch[y][1]==x) ? x : y); 57 } 58 }// 59 void access(int x){ 60 push(x); 61 for(int y=0;x;y=x,x=fa[x]){ 62 splay(x); 63 // fa[ch[x][1]]=0; 64 ch[x][1]=y; 65 pushup(x); 66 } 67 }// 68 int find(int x){ 69 access(x);splay(x); 70 while(ch[x][0])x=ch[x][0]; 71 return x; 72 }// 73 void make_rt(int x){ 74 access(x);splay(x); 75 rev[x]^=1; 76 }// 77 void link(int x,int y){ 78 make_rt(x); 79 fa[x]=y; 80 }// 81 void cut(int x,int y){ 82 make_rt(x); 83 access(y);splay(y); 84 ch[y][0]=fa[x]=0; 85 pushup(y); 86 }// 87 int ask(int x,int y){ 88 make_rt(x); 89 access(y);splay(y); 90 return mn[y]; 91 }// 92 void ins(int&k,int last,int l,int r,int x,int v){ 93 sum[k=++sz]=sum[last]+v; 94 ls[k]=ls[last];rs[k]=rs[last]; 95 int mid=(l+r)>>1; 96 if(l==r)return ; 97 if(x<=mid)ins(ls[k],ls[last],l,mid,x,v); 98 else ins(rs[k],rs[last],mid+1,r,x,v); 99 }// 100 int query(int k,int l,int r,int x,int y){ 101 if(l==x&&r==y)return sum[k]; 102 else{ 103 int mid=(l+r)>>1; 104 if(y<=mid)return query(ls[k],l,mid,x,y); 105 else if(x>mid)return query(rs[k],mid+1,r,x,y); 106 else return query(ls[k],l,mid,x,mid) + query(rs[k],mid+1,r,mid+1,y); 107 } 108 }// 109 int main(){ 110 // freopen("bzoj3514.in","r",stdin); 111 // freopen("bzoj3514.out","w",stdout); 112 n=rd();m=rd();q=rd();typ=rd(); 113 mn[0]=val[0]=inf; 114 for(int i=1;i<=n;i++)val[i]=inf; 115 for(int i=1;i<=m;i++)e[i]=(edge){rd(),rd()},val[i+n]=i; 116 for(int i=1;i<=m;i++){ 117 int u=e[i].u , v=e[i].v; 118 if(u==v){rt[i]=rt[i-1];continue;} 119 int fu = find(u) , fv = find(v); 120 if(fu==fv){ 121 int x = ask(u,v); 122 ins(rt[i],rt[i-1],1,m,x,-1); 123 cut(e[x].u,x+n),cut(e[x].v,x+n); 124 }else rt[i]=rt[i-1]; 125 ins(rt[i],rt[i],1,m,i,1); 126 link(u,i+n),link(v,i+n); 127 }// 128 for(int i=1,l,r,ans=0;i<=q;i++){ 129 l=rd();r=rd(); 130 if(typ)l^=ans,r^=ans; 131 ans = n - query(rt[r],1,m,l,r); 132 printf("%d ",ans); 133 }// 134 return 0; 135 }//by tkys_Austin; 136