GERALD07加强版题解

题目描述:

  N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

输入格式:

  第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。 接下来M行,代表图中的每条边。 接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

输出格式:

  K行每行一个整数代表该组询问的联通块个数。

题解:

  连通问题首先考虑LCT。

  考虑连通块个数的计算方法。

  连通块个数=点数-去掉重边后的边数。

  逐个枚举边,如果这条边连接的两个点没有连通,连接这条边;反之,把两点间最早的边弹出,连接这条边,并记录弹出边的编号。

  每次查询区间时,如果这条边弹出的边在区间内,那么这条边是无效的。

  所以问题转化为求区间内小于某个数的数的个数,可以主席树维护。

  时间复杂度$O(nlog_n)$

Code:

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 const int N=400010;
  5 const int inf=1e9+10;
  6 int n,m,k,ty,cnt,top;
  7 int a[N<<1],st[N<<1],ch[N<<1][2],f[N<<1],rev[N<<1],mi[N<<1];
  8 int u[N],v[N],rt[N],b[N],an[N];
  9 struct seg{
 10     int lc,rc,w;
 11 }t[N<<5];
 12 int read()
 13 {
 14     int s=0;char c=getchar();
 15     while(c<'0'||c>'9') c=getchar();
 16     while(c>='0'&&c<='9'){
 17         s=(s<<3)+(s<<1)+c-'0';
 18         c=getchar();
 19     }
 20     return s;
 21 }
 22 int get(int x)
 23 {
 24     return ch[f[x]][1]==x;
 25 }
 26 bool isroot(int x)
 27 {
 28     return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
 29 }
 30 void pushup(int x)
 31 {
 32     mi[x]=a[x];
 33     if(ch[x][0]) mi[x]=min(mi[x],mi[ch[x][0]]);
 34     if(ch[x][1]) mi[x]=min(mi[x],mi[ch[x][1]]);
 35 }
 36 void pushdown(int x)
 37 {
 38     if(rev[x]){
 39         swap(ch[x][0],ch[x][1]);
 40         if(ch[x][0]) rev[ch[x][0]]^=1;
 41         if(ch[x][1]) rev[ch[x][1]]^=1;
 42         rev[x]=0;
 43     }
 44 }
 45 void rotate(int x)
 46 {
 47     int y=f[x],z=f[y],k=get(x);
 48     if(!isroot(y)){
 49         if(ch[z][0]==y) ch[z][0]=x;
 50         else ch[z][1]=x;
 51     }
 52     f[x]=z;f[y]=x;f[ch[x][k^1]]=y;
 53     ch[y][k]=ch[x][k^1];ch[x][k^1]=y;
 54     pushup(y);pushup(x);
 55 }
 56 void splay(int x)
 57 {
 58     top=0;st[++top]=x;
 59     for(int i=x;!isroot(i);i=f[i]) st[++top]=f[i];
 60     for(int i=top;i>=1;i--) pushdown(st[i]);
 61     while(!isroot(x)){
 62         int y=f[x];
 63         if(!isroot(y)){
 64             if(get(x)==get(y)) rotate(y);
 65             else rotate(x);
 66         }
 67         rotate(x);
 68     }
 69 }
 70 void access(int x)
 71 {
 72     for(int y=0;x;y=x,x=f[x]){
 73         splay(x);ch[x][1]=y;pushup(x);
 74     }
 75 }
 76 void makeroot(int x)
 77 {
 78     access(x);splay(x);
 79     rev[x]^=1;
 80 }
 81 void split(int x,int y)
 82 {
 83     makeroot(x);
 84     access(y);splay(y);
 85 }
 86 void link(int x,int y)
 87 {
 88     makeroot(x);
 89     f[x]=y;
 90 }
 91 void cut(int x,int y)
 92 {
 93     split(x,y);
 94     f[x]=ch[y][0]=0;
 95 }
 96 int find(int x)
 97 {
 98     access(x);splay(x);
 99     pushdown(x);
100     while(ch[x][0]){
101         pushdown(ch[x][0]);
102         x=ch[x][0];
103     }
104     splay(x);
105     return x;
106 }
107 void insert(int lk,int &rk,int l,int r,int x)
108 {
109     if(rk==0) rk=++cnt;
110     t[rk].w=t[lk].w+1;
111     if(l==r) return;
112     int mid=(l+r)>>1;
113     if(x<=mid){
114         t[rk].rc=t[lk].rc;
115         insert(t[lk].lc,t[rk].lc,l,mid,x);
116     }
117     else{
118         t[rk].lc=t[lk].lc;
119         insert(t[lk].rc,t[rk].rc,mid+1,r,x);
120     }
121 }
122 int que(int lk,int rk,int L,int R,int l,int r)
123 {
124     if(L>=l&&R<=r) return t[rk].w-t[lk].w;
125     int mid=(L+R)>>1;
126     if(r<=mid) return que(t[lk].lc,t[rk].lc,L,mid,l,r);
127     else if(l>mid) return que(t[lk].rc,t[rk].rc,mid+1,R,l,r);
128     else return que(t[lk].lc,t[rk].lc,L,mid,l,r)+que(t[lk].rc,t[rk].rc,mid+1,R,l,r);
129 }
130 int main()
131 {
132     n=read();m=read();k=read();ty=read();
133     for(int i=1;i<=n;i++) a[i]=inf;
134     for(int i=1;i<=m;i++){
135         u[i]=read();v[i]=read();a[i+n]=i;
136         if(u[i]!=v[i]){
137             int x=find(u[i]),y=find(v[i]);
138             if(x==y){
139                 split(u[i],v[i]);
140                 b[i]=mi[v[i]];
141                 cut(u[b[i]],b[i]+n);
142                 cut(b[i]+n,v[b[i]]);
143             }
144             link(u[i],i+n);
145             link(i+n,v[i]);
146             insert(rt[i-1],rt[i],0,m,b[i]);
147         }
148         else rt[i]=rt[i-1];
149     }
150     for(int i=1;i<=k;i++){
151         int l=read(),r=read();
152         if(ty){
153             l^=an[i-1];r^=an[i-1];
154         }
155         an[i]=n-que(rt[l-1],rt[r],0,m,0,l-1);
156     }
157     for(int i=1;i<=k;i++) printf("%d\n",an[i]);
158     return 0;
159 }
View Code
posted @ 2019-09-23 17:52  hz_Rockstar  阅读(266)  评论(0编辑  收藏  举报