您的位置:首页 > 其它

BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

2018-04-29 22:30 381 查看

BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

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。

 把这m条边按顺序插进去,维护边的编号最小的边的编号。

当出现两个点连通时把路径上编号最小的删掉,并记录下每条边删除的时间t。

对于询问l~r,假设这些边放进去,也会有一些边被删除。

连通块个数=n-((r-l+1)-被删除的边数)。

然后知道被删除的边数刚好是t小于等于r的那些边,主席树查一下即可。

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 400050
#define ls ch

[0] #define rs ch[p][1] #define get(x) (ch[f[x]][1]==x) int ch [2],f ,rev ,n,m,k,siz[N*30],t ,val ,mx ,tot,cnt,lson[N*30],rson[N*30]; int xx ,yy ,root ; inline bool isrt(int p) { return ch[f[p]][0]!=p&&ch[f[p]][1]!=p; } inline void pushup(int p) { mx[p]=p; if(val[mx[ls]]>val[mx[p]]) mx[p]=mx[ls]; if(val[mx[rs]]>val[mx[p]]) mx[p]=mx[rs]; } inline void pushdown(int p) { if(rev[p]) { swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]); rev[ls]^=1; rev[rs]^=1; rev[p]=0; } } void update(int p) { if(!isrt(p)) update(f[p]); pushdown(p); } void rotate(int x) { int y=f[x],z=f[y],k=get(x); if(!isrt(y)) ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][!k]; f[ch[y][k]]=y; ch[x][!k]=y; f[y]=x; f[x]=z; pushup(y); pushup(x); } void splay(int x) { update(x); for(int d;d=f[x],!isrt(x);rotate(x)) if(!isrt(d)) rotate(get(d)==get(x)?d:x); } void access(int p) { int t=0; while(p) splay(p),rs=t,pushup(p),t=p,p=f[p]; } void makeroot(int p) { access(p); splay(p); swap(ls,rs); rev[p]^=1; } void link(int x,int p) { makeroot(x); splay(p); f[x]=p; } void cut(int x,int p) { makeroot(x); access(p); splay(p); ls=f[x]=0; } int find(int p) { access(p); splay(p); while(ls) pushdown(p),p=ls; return p; } void insert(int &y,int x,int l,int r,int v) { y=++tot; siz[y]=siz[x]+1; if(l==r) return ; int mid=(l+r)>>1; if(v<=mid) rson[y]=rson[x],insert(lson[y],lson[x],l,mid,v); else lson[y]=lson[x],insert(rson[y],rson[x],mid+1,r,v); } int query(int x,int y,int l,int r,int k) { if(k>=r) return siz[x]-siz[y]; int mid=(l+r)>>1,re=0; if(1<=mid) re+=query(lson[x],lson[y],l,mid,k); if(k>mid) re+=query(rson[x],rson[y],mid+1,r,k); return re; } int inq(int x,int p) { makeroot(x); access(p); splay(p); return mx[p]; } int main() { int type; scanf("%d%d%d%d",&n,&m,&k,&type); int i,x,y; cnt=n; for(i=1;i<=n;i++) mx[i]=i; for(i=1;i<=m;i++) { cnt++; scanf("%d%d",&x,&y); xx[cnt]=x; yy[cnt]=y; if(x==y) { t[i]=i; continue; } int t1=find(x),t2=find(y); if(t1!=t2) { val[cnt]=m-i+1; mx[cnt]=cnt; link(x,cnt); link(cnt,y); }else { val[cnt]=m-i+1; mx[cnt]=cnt; int d=inq(x,y); //printf("%d\n",val[d]); t[m-val[d]+1]=i; cut(xx[d],d); cut(d,yy[d]); link(x,cnt); link(cnt,y); } } for(i=1;i<=m;i++) { if(!t[i]) t[i]=m+1; insert(root[i],root[i-1],1,m+1,t[i]); } int ans=0; while(k--) { scanf("%d%d",&x,&y); if(!type) ans=0; x^=ans; y^=ans; ans=n-y+x-1+query(root[y],root[x-1],1,m+1,y); printf("%d\n",ans); } //for(i=1;i<=m;i++) printf("%d\n",t[i]); }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: