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。

 

题解:
http://hzwer.com/4358.html
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 char ch;
 8 bool ok;
 9 void read(int &x){
10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
12     if (ok) x=-x;
13 }
14 const int maxn=400005;
15 const int maxnode=4000000;
16 const int inf=2147483647;
17 int n,m,q,type,a[maxn],b[maxn],l,r,pos[maxn],pop[maxn],root[maxn],ans;
18 struct LCT{
19     int son[maxn][2],fa[maxn],val[maxn],minv[maxn],pos[maxn],id[maxn],rev[maxn];
20     void init(int x,int v,int i){val[x]=minv[x]=v,pos[x]=id[x]=i;}
21     int which(int x){return son[fa[x]][1]==x;}
22     bool isroot(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
23     void reverse(int x){if (x) rev[x]^=1;}
24     void pushdown(int x){if (rev[x]) swap(son[x][0],son[x][1]),reverse(son[x][0]),reverse(son[x][1]),rev[x]=0;}
25     void relax(int x){if (!isroot(x)) relax(fa[x]); pushdown(x);}
26     void update(int x,int y){if (minv[x]>minv[y]) minv[x]=minv[y],pos[x]=pos[y];}
27     void update(int x){
28         minv[x]=val[x],pos[x]=id[x];
29         if (son[x][0]) update(x,son[x][0]);
30         if (son[x][1]) update(x,son[x][1]);
31     }
32     void rotate(int x){
33         int y=fa[x],z=fa[y],d=which(x),dd=which(y);
34         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],fa[x]=fa[y];
35         if (!isroot(y)) son[z][dd]=x;
36         son[x][d^1]=y,fa[y]=x,update(y),update(x);
37     }
38     void splay(int x){
39         relax(x);
40         while (!isroot(x)){
41             if (isroot(fa[x])) rotate(x);
42             else if (which(x)==which(fa[x])) rotate(fa[x]),rotate(x);
43             else rotate(x),rotate(x);
44         }
45     }
46     void access(int x){for (int p=0;x;x=fa[x]) splay(x),fa[son[x][1]=p]=x,update(p=x);}
47     void make_root(int x){access(x),splay(x),reverse(x);}
48     int find(int x){
49         access(x),splay(x);
50         for (;son[x][0];x=son[x][0]) pushdown(x);
51         return x;
52     }
53     int query(int x,int y){
54         if (find(x)==find(y)){make_root(x),access(y),splay(y);return pos[y];}
55         else return 0;
56     }
57     void cut(int x,int y){make_root(x),access(y),splay(y),fa[x]=0,son[y][0]=0;}
58     void link(int x,int y){make_root(x),fa[x]=y;}
59 }lct;
60 struct seg{
61     int tot,sum[maxnode],son[maxnode][2];
62     void insert(int p,int &k,int l,int r,int x){
63         sum[k=++tot]=sum[p]+1;
64         if (l==r) return;
65         int m=(l+r)>>1;
66         if (x<=m) son[k][1]=son[p][1],insert(son[p][0],son[k][0],l,m,x);
67         else son[k][0]=son[p][0],insert(son[p][1],son[k][1],m+1,r,x);
68     }
69     int query(int k,int l,int r,int x){
70         if (l==r) return sum[k];
71         int m=(l+r)>>1;
72         if (x<=m) return query(son[k][0],l,m,x);
73         else return sum[son[k][0]]+query(son[k][1],m+1,r,x);
74     }
75     int query(int a,int b,int x){return query(b,0,m,x)-query(a,0,m,x);}
76 }T;
77 int main(){
78     read(n),read(m),read(q),read(type);
79     for (int i=1;i<=n;i++) lct.init(i,inf,0);
80     for (int i=1;i<=m;i++) lct.init(n+i,i,i);
81     for (int i=1;i<=m;i++){
82         read(a[i]),read(b[i]);
83         if (a[i]!=b[i]){
84             pop[i]=lct.query(a[i],b[i]);
85             if (pop[i]) lct.cut(a[pop[i]],pop[i]+n),lct.cut(b[pop[i]],pop[i]+n);
86             lct.link(a[i],n+i),lct.link(b[i],n+i);
87         }
88         else pop[i]=i;
89     }
90     for (int i=1;i<=m;i++) T.insert(root[i-1],root[i],0,m,pop[i]);
91     while (q--){
92         read(l),read(r);
93         if (type) l^=ans,r^=ans;
94         ans=n-T.query(root[l-1],root[r],l-1);
95         printf("%d\n",ans);
96     }
97     return 0;
98 }

 

转载于:https://www.cnblogs.com/chenyushuo/p/5225158.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值