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

Sample Output

2
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 }

 

posted @ 2017-02-28 10:42  wfj_2048  阅读(234)  评论(3编辑  收藏  举报