bzoj3514 Codechef MARCH14 GERALD07加强版
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
正解:link-cut tree+主席树。
这题一眼看上去就不会做woc。。其实我知道一个暴力的莫队+lctO(n√nlogn)做法,不过强制在线。。
有一个比较猎奇的做法:首先把边依次加到图中,若当前这条边与图中的边形成了环,那么把这个环中最早加进来的边弹出去
并将每条边把哪条边弹了出去记录下来:ntr[i] = j,特别地,要是没有弹出边,ntr[i] = 0;
这个显然是可以用LCT来弄的对吧。
然后对于每个询问,我们的答案就是对l~r中ntr小于l的边求和,并用n减去这个值
正确性可以YY一下:
如果一条边的ntr >= l,那么显然他可以与从l ~ r中的边形成环,那么它对答案没有贡献
反之如果一条边的ntr < l那么它与从l ~ r中的边是不能形成环的,那么他对答案的贡献为-1
对于查询从l ~ r中有多少边的ntr小于l,我反正是用的函数式线段树
——hzwer博客
然后还有一个特判,如果i边是自环,那nxt[i]=i,还好样例就有。。然后虽然一次AC了,这题我却写了一个多小时,LCT我都忘记写了。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (200010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define min(a,b) (a<b ? a : b) 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 21 22 using namespace std; 23 24 struct edge{ int u,v; }g[N]; 25 26 int sum[2*N],val[2*N],lazy[2*N],ch[2*N][2],fa[2*N],st[2*N]; 27 int s[20*N],ls[20*N],rs[20*N],rt[N],nxt[N],sz,n,m,k,type,ans; 28 29 il int gi(){ 30 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 31 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 32 } 33 34 il void pushdown(RG int x){ lazy[x]=0,lazy[ch[x][0]]^=1,lazy[ch[x][1]]^=1,swap(ch[x][0],ch[x][1]); return; } 35 36 il void pushup(RG int x){ 37 sum[x]=val[x]; 38 if (ch[x][0]) sum[x]=min(sum[x],sum[ch[x][0]]); 39 if (ch[x][1]) sum[x]=min(sum[x],sum[ch[x][1]]); 40 return; 41 } 42 43 il int isroot(RG int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; } 44 45 il void rotate(RG int x){ 46 RG int y=fa[x],z=fa[y],k=ch[y][0]==x; 47 if (!isroot(y)) ch[z][ch[z][1]==y]=x; fa[x]=z; 48 ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y; 49 ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return; 50 } 51 52 il void splay(RG int x){ 53 RG int top=0; st[++top]=x; 54 for (RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; 55 for (RG int i=top;i;--i) if (lazy[st[i]]) pushdown(st[i]); 56 while (!isroot(x)){ 57 RG int y=fa[x],z=fa[y]; 58 if (!isroot(y)){ 59 ((ch[z][0]==y)^(ch[y][0]==x)) ? rotate(x) : rotate(y); 60 } 61 rotate(x); 62 } 63 return; 64 } 65 66 il void access(RG int x){ RG int t=0; while (x) splay(x),ch[x][1]=t,pushup(x),t=x,x=fa[x]; return; } 67 68 il void makeroot(RG int x){ access(x),splay(x),lazy[x]^=1; return; } 69 70 il void link(RG int x,RG int y){ makeroot(x),fa[x]=y; return; } 71 72 il void cut(RG int x,RG int y){ makeroot(x),access(y),splay(y),fa[x]=ch[y][0]=0; return; } 73 74 il int query(RG int x,RG int y){ makeroot(x),access(y),splay(y); return sum[y]; } 75 76 il int find(RG int x){ access(x),splay(x); while (ch[x][0]) x=ch[x][0]; return x; } 77 78 il void insert(RG int x,RG int &y,RG int l,RG int r,RG int v){ 79 s[y=++sz]=s[x]+1,ls[y]=ls[x],rs[y]=rs[x]; if (l==r) return; RG int mid=(l+r)>>1; 80 v<=mid ? insert(ls[x],ls[y],l,mid,v) : insert(rs[x],rs[y],mid+1,r,v); return; 81 } 82 83 il int query(RG int x,RG int y,RG int l,RG int r,RG int v){ 84 if (l==r) return 0; RG int mid=(l+r)>>1; 85 return v<=mid ? query(ls[x],ls[y],l,mid,v) : query(rs[x],rs[y],mid+1,r,v)+s[ls[y]]-s[ls[x]]; 86 } 87 88 il void work(){ 89 n=gi(),m=gi(),k=gi(),type=gi(); RG int l,r; 90 for (RG int i=1;i<=n;++i) val[i]=inf; 91 for (RG int i=1;i<=m;++i) val[n+i]=i; 92 for (RG int i=1;i<=m;++i){ 93 g[i].u=gi(),g[i].v=gi(); 94 if (g[i].u==g[i].v){ nxt[i]=i; continue; } 95 if (find(g[i].u)==find(g[i].v)){ 96 RG int res=query(g[i].u,g[i].v); 97 nxt[i]=res,cut(g[res].u,n+res),cut(g[res].v,n+res); 98 } 99 link(g[i].u,n+i),link(g[i].v,n+i); 100 } 101 for (RG int i=1;i<=m;++i) insert(rt[i-1],rt[i],0,m,nxt[i]); 102 for (RG int i=1;i<=k;++i){ 103 l=gi(),r=gi(); if (type) l^=ans,r^=ans; 104 ans=n-query(rt[l-1],rt[r],0,m,l); printf("%d\n",ans); 105 } 106 return; 107 } 108 109 int main(){ 110 File("graph"); 111 work(); 112 return 0; 113 }