GERALD07加强版题解

Posted hz-rockstar

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于GERALD07加强版题解的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj3514]: Codechef MARCH14 GERALD07加强版

GERALD07加强版:lct,主席树,边化点

Bzoj3514: Codechef MARCH14 GERALD07加强版

bzoj 3514 Codechef MARCH14 GERALD07加强版 主席树+LCT

BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree+划分树

bzoj3514: Codechef MARCH14 GERALD07加强版