【bzoj3514】Codechef MARCH14 GERALD07加强版

3514: Codechef MARCH14 GERALD07加强版

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 2395  Solved: 922
[Submit][Status][Discuss]

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

 

Source

[Submit][Status][Discuss]

题意:无向图,维护边的编号在[l,r]的边形成的点连通块个数;

题解:  一般有一下一些情况:

           ① 无向图,维护边的编号在[l,r]的点连通块个数
           ②无向图,维护点的编号在[l,r]的生成子图连通块个数;

           ③强制在线??

题解:好神

         ①将边按照编号不断加入LCT,如果没有形成环就直接加入,如果形成了一个环就删去环上编号最小的边,这样LCT里面会保留尽量靠后的边,将询问按右端点排序,答案是n - LCT里面编号在[l,r]的数目;

            可以用树状数组维护边编号;

          ②将点看成一个序列,将边(u,v)看成一条线段并按右端点排序,按照一样的方法不断加入边,只是这次有环就删去左端点编号最小的值,答案同样是[r-l+1]-LCT里面左端点编号在[l,r]的数目;

            也可以用树状数组维护;

          ③离线太白痴了,树状数组换成主席树就可以了,LCT维护边的信息时将边看成一个点;

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 #include<cmath>
  7 #include<vector>
  8 #include<stack>
  9 #include<map>
 10 #define Run(i,l,r) for(int i=l;i<=r;i++)
 11 #define Don(i,l,r) for(int i=l;i>=r;i--)
 12 #define ll long long
 13 #define inf 0x3f3f3f3f
 14 using namespace std;
 15 const int N=200010; 
 16 int n,m,q,sz,typ,rt[N],ls[N*40],rs[N*40],sum[N*40];
 17 int ch[N<<1][2],fa[N<<1],mn[N<<1],val[N<<1],rev[N<<1];
 18 struct edge{int u,v;}e[N];
 19 char gc(){
 20     static char*p1,*p2,s[1000000];
 21     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
 22     return(p1==p2)?EOF:*p1++; 
 23 }//
 24 int rd(){
 25     int x=0; char c=gc();
 26     while(c<'0'||c>'9')c=gc();
 27     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
 28     return x;
 29 }//
 30 bool is_rt(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}//
 31 void pushup(int x){mn[x]=min(val[x],min(mn[ch[x][0]],mn[ch[x][1]]));}//
 32 void pushdown(int x){
 33     if(rev[x]){
 34         swap(ch[x][0],ch[x][1]);
 35         rev[ch[x][0]]^=1;
 36         rev[ch[x][1]]^=1;
 37         rev[x]^=1;
 38     }
 39 }//
 40 void rotate(int x){
 41     int y=fa[x] , z=fa[y];
 42     if(!is_rt(y))ch[z][ch[z][1]==y]=x;
 43     int l=ch[y][1]==x,r=l^1;
 44     fa[y]=x;fa[x]=z;fa[ch[x][r]]=y;
 45     ch[y][l]=ch[x][r];ch[x][r]=y;
 46     pushup(y),pushup(x);
 47 }//
 48 void push(int x){
 49     if(!is_rt(x))push(fa[x]);
 50     pushdown(x);
 51 }//
 52 void splay(int x){
 53     push(x);
 54     for(int y,z;!is_rt(x);rotate(x)){
 55         y=fa[x],z=fa[y];
 56         if(!is_rt(y))rotate((ch[z][1]==y)^(ch[y][1]==x) ? x : y);
 57     }
 58 }//
 59 void access(int x){
 60     push(x);
 61     for(int y=0;x;y=x,x=fa[x]){
 62         splay(x);
 63 //      fa[ch[x][1]]=0;  
 64         ch[x][1]=y;
 65         pushup(x);
 66     }
 67 }//
 68 int find(int x){
 69     access(x);splay(x);
 70     while(ch[x][0])x=ch[x][0];
 71     return x;
 72 }//
 73 void make_rt(int x){
 74     access(x);splay(x);
 75     rev[x]^=1;
 76 }//
 77 void link(int x,int y){
 78     make_rt(x);
 79     fa[x]=y;
 80 }//
 81 void cut(int x,int y){
 82     make_rt(x);
 83     access(y);splay(y);
 84     ch[y][0]=fa[x]=0;
 85     pushup(y);
 86 }//
 87 int ask(int x,int y){
 88     make_rt(x);
 89     access(y);splay(y);
 90     return mn[y];
 91 }//
 92 void ins(int&k,int last,int l,int r,int x,int v){
 93     sum[k=++sz]=sum[last]+v;
 94     ls[k]=ls[last];rs[k]=rs[last];
 95     int mid=(l+r)>>1;
 96     if(l==r)return ;
 97     if(x<=mid)ins(ls[k],ls[last],l,mid,x,v);
 98     else ins(rs[k],rs[last],mid+1,r,x,v);
 99 }//
100 int query(int k,int l,int r,int x,int y){
101     if(l==x&&r==y)return sum[k];
102     else{
103         int mid=(l+r)>>1;
104         if(y<=mid)return query(ls[k],l,mid,x,y);
105         else if(x>mid)return query(rs[k],mid+1,r,x,y);
106         else return query(ls[k],l,mid,x,mid) + query(rs[k],mid+1,r,mid+1,y);
107     }
108 }//
109 int main(){
110 //  freopen("bzoj3514.in","r",stdin);
111 //  freopen("bzoj3514.out","w",stdout);
112     n=rd();m=rd();q=rd();typ=rd();
113     mn[0]=val[0]=inf;
114     for(int i=1;i<=n;i++)val[i]=inf;
115     for(int i=1;i<=m;i++)e[i]=(edge){rd(),rd()},val[i+n]=i;
116     for(int i=1;i<=m;i++){
117         int u=e[i].u , v=e[i].v;
118         if(u==v){rt[i]=rt[i-1];continue;}
119         int fu = find(u) , fv = find(v);
120         if(fu==fv){
121             int x = ask(u,v);
122             ins(rt[i],rt[i-1],1,m,x,-1);
123             cut(e[x].u,x+n),cut(e[x].v,x+n);
124         }else rt[i]=rt[i-1];
125         ins(rt[i],rt[i],1,m,i,1);
126         link(u,i+n),link(v,i+n);
127     }//
128     for(int i=1,l,r,ans=0;i<=q;i++){
129         l=rd();r=rd();
130         if(typ)l^=ans,r^=ans;
131         ans = n - query(rt[r],1,m,l,r);
132         printf("%d\n",ans);
133     }//
134     return 0;
135 }//by tkys_Austin;
136 
View Code

 

 

 

posted @ 2018-10-16 07:12  大米饼  阅读(187)  评论(0编辑  收藏  举报