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。

正解:LCT加主席树

解题报告:当一条边加进来的时候,如果产生了环,我们把环上最小的一条边删掉并记录,如果没有环,记录为0,到时候进行区间查询的时候,我们可以访问这个数组,如果被删掉的边小于l(0也包括),说明这条边联通了两个本来不连通的区间,然后答案-1即可,这样题目就变成了给定一个区间,求小于这个数的元素的数量,删加边显然用lct做。

 

  1 #include <iostream>
  2 #include <iomanip>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <cmath>
  6 #include <string>
  7 #include <cstring>
  8 #include <algorithm>
  9 #define MIN(a,b) (a<b?a:b)
 10 #define RG register
 11 const int N = 500000;
 12 const int M = 15000000;
 13 const int inf = 2147483641;
 14 
 15 using namespace std;
 16 
 17 int gi(){
 18     RG char ch=getchar();RG int x=0;
 19     while(ch<'0' || ch>'9') ch=getchar();
 20     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
 21     return x;
 22 }
 23 
 24 int fa[N],c[2][N],rev[N],st[N],lt[N],mn[N],a[N],b[N],rt[N];
 25 int n,m,k,type,cnt;
 26 
 27 struct date{
 28     int l,r,s;
 29 }tr[M];
 30 
 31 int isroot(int x){
 32     return c[0][fa[x]]!=x && c[1][fa[x]]!=x;
 33 }
 34 
 35 void pushdown(int x){
 36     if (rev[x]==0) return;
 37     rev[x]^=1,rev[c[0][x]]^=1,rev[c[1][x]]^=1;
 38     swap(c[0][x],c[1][x]);
 39     return;
 40 }
 41 
 42 void update(int x){
 43     mn[x]=x<=n?inf:x;
 44     mn[x]=MIN(mn[x],MIN(mn[c[0][x]],mn[c[1][x]]));
 45     return;
 46 }
 47 
 48 void rotate(int x){
 49     int l,r,y=fa[x],z=fa[y];
 50     if (c[0][y]==x) l=0;
 51     else l=1;r=l^1;
 52     if (!isroot(y))
 53         if (c[0][z]==y) c[0][z]=x;
 54         else c[1][z]=x;
 55     fa[x]=z,fa[y]=x,fa[c[r][x]]=y;
 56     c[l][y]=c[r][x],c[r][x]=y;
 57     update(y),update(x);
 58     return;
 59 }
 60 
 61 void splay(int x){
 62     int tot=0;st[++tot]=x;
 63     for (RG int i=x; !isroot(i); i=fa[i]) st[++tot]=fa[i];
 64     for (RG int i=tot; i; --i) pushdown(st[i]);
 65     while(!isroot(x)){
 66         int y=fa[x],z=fa[y];
 67         if (!isroot(y))
 68             if (c[0][y]==x ^ c[0][z]==y) rotate(x);
 69             else rotate(y);
 70         rotate(x);
 71     }
 72     return;
 73 }
 74 
 75 void access(int x){
 76     int t=0;
 77     while(x){
 78         splay(x);
 79         c[1][x]=t;update(x);
 80         t=x,x=fa[x];
 81     }
 82     return;
 83 }
 84 
 85 void rever(int x){
 86     access(x),splay(x),rev[x]^=1;
 87     return;
 88 }
 89 
 90 void link(int l,int r){
 91     rever(l),fa[l]=r;
 92     return;
 93 }
 94 
 95 void cut(int l,int r){
 96     rever(l),access(r),splay(r);
 97     c[0][r]=fa[l]=0;
 98     return;
 99 }
100 
101 int query(int x){
102     access(x),splay(x);
103     while(c[0][x]) x=c[0][x];
104     return x;
105 }
106 
107 void build(int &t,int l,int r,int s){
108     tr[++cnt]=tr[t];t=cnt;
109     ++tr[t].s;
110     if (l==r) return;
111     int mid=(l+r)>>1;
112     if (s<=mid) build(tr[t].l,l,mid,s);
113     else build(tr[t].r,mid+1,r,s);
114     return;
115 }
116 
117 int query(int x,int l,int r,int ql,int qr){
118     if (ql>qr) return 0;
119     if (ql<=l && r<=qr) return tr[x].s;
120     int ans=0,mid=(l+r)>>1;
121     if (ql<=mid) ans+=query(tr[x].l,l,mid,ql,qr);
122     if (qr>mid) ans+=query(tr[x].r,mid+1,r,ql,qr);
123     return ans;
124 }
125 
126 int main(){
127     freopen("splay.in","r",stdin);
128     freopen("splay.out","w",stdout);
129     n=gi(),m=gi(),k=gi(),type=gi();
130     for (RG int i=0; i<=n; ++i) mn[i]=inf;
131     for (RG int i=1; i<=m; ++i){
132         int l=gi(),r=gi();
133         if (l==r) {lt[i]=m;continue;}
134         a[i]=l,b[i]=r;
135         if (query(l)==query(r)){
136             rever(l),access(r),splay(r);
137             int z=a[mn[r]-n],y=b[mn[r]-n],k=mn[r];
138             lt[i]=mn[r]-n;
139             cut(z,k),cut(k,y);
140         }
141         link(l,i+n),link(i+n,r);
142     }
143     for (RG int i=1; i<=m; ++i){
144         int g=lt[i];
145         rt[i]=rt[i-1];
146         build(rt[i],0,m,g);
147     }
148     int jl=0;
149     for (RG int i=1; i<=k; ++i){
150         int l=gi()^jl,r=gi()^jl,ans=n;
151         ans-=query(rt[r],0,m,0,l-1)-query(rt[l-1],0,m,0,l-1);
152         printf("%d\n",ans);
153         if (type) jl=ans;
154     }
155     return 0;
156 }

 


 

posted @ 2017-03-01 15:37  Cjk_2001  阅读(155)  评论(1编辑  收藏  举报