【LCT+主席树】BZOJ3514 Codechef MARCH14 GERALD07加强版


3514: Codechef MARCH14 GERALD07加强版

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 2023  Solved: 778
[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

 

题解

这道题是一道思路好题(废话)

我们可以维护每条边关于加入时间的最大生成树

然后如果弹出一条边,记录这条边被谁弹出

然后显然对于区间 [l,r] ti 大于 r 的边一定不会被删除

并且所有 ti 小于等于 r 的边一定被删除

因为 ti 小于等于 r 的边一定在一个所有边编号都小于等于 r 并且都大

所以这段区间的答案为n-区间内大于r的数的个数

可持久化权值线段树维护下

代码

//by 减维
#include<iostream>
#include
<cstdio>
#include
<cstring>
#include
<queue>
#include
<bitset>
#include
<set>
#include
<cmath>
#include
<vector>
#include
<set>
#include
<map>
#include
<ctime>
#include
<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define inf (1<<30)
#define maxn 400005
#define mpr make_pair
#define eps 1e-8
using namespace std;

inline
int read()
{
int ret=0;bool fla=0;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-'){fla=1;ch=getchar();}
while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
return fla?-ret:ret;
}

struct edge{
int x,y;
}e[maxn];

struct tree{
int l,r,v;
}t[maxn
<<5];

int n,m,q,tt,ans,cnt,rt[maxn],fa[maxn],son[maxn][2],val[maxn],rev[maxn],pos[maxn],tim[maxn];

il
bool pdp(int x){return son[fa[x]][1]==x;}
il
bool isrt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
il
void rever(int x){rev[x]^=1;swap(son[x][0],son[x][1]);}

il
void upda(int x)
{
pos[x]
=x;
if(son[x][0]&&val[pos[son[x][0]]]<val[pos[x]]) pos[x]=pos[son[x][0]];
if(son[x][1]&&val[pos[son[x][1]]]<val[pos[x]]) pos[x]=pos[son[x][1]];
}

il
void pdn(int x)
{
if(rev[x])
{
if(son[x][0]) rever(son[x][0]);
if(son[x][1]) rever(son[x][1]);
rev[x]
=0;
}
}

void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);}

il
void rot(int x)
{
int f=fa[x],g=fa[f],o=pdp(x);
if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g;
son[f][o]
=son[x][!o];fa[son[f][o]]=f;
son[x][
!o]=f;fa[f]=x;
upda(f),upda(x);
}

il
void splay(int x)
{
pd(x);
for(;!isrt(x);rot(x))
if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x);
}

il
void acc(int x)
{
for(int y=0;x;y=x,x=fa[x])
splay(x),son[x][
1]=y,upda(x);
}

il
int find(int x)
{
acc(x);splay(x);
while(son[x][0]) pd(x),x=son[x][0];
return x;
}

il
void bert(int x){acc(x);splay(x);rever(x);}
il
void spli(int x,int y){bert(x);acc(y);splay(y);}
il
void cut(int x,int y){spli(x,y);fa[x]=son[y][0]=0;upda(y);}

il
void link(int x,int y,int z)
{
if(find(x)==find(y))
{
spli(x,y);
int aa=pos[y];//printf("%d\n",aa);
cut(e[aa-n].x,aa);cut(e[aa-n].y,aa);
tim[aa
-n]=z-n;
}
bert(x);fa[x]
=z;
bert(y);fa[y]
=z;
}

void upd(int x)
{
t[x].v
=t[t[x].l].v+t[t[x].r].v;
}

void build(int l,int r,int las,int &now,int v)
{
now
=++cnt;t[now]=t[las];t[now].v++;
if(l==r)return ;
int mid=(l+r)>>1;
if(v<=mid) build(l,mid,t[las].l,t[now].l,v);
else build(mid+1,r,t[las].r,t[now].r,v);
}

int query(int l,int r,int x,int y,int v)
{
if(l==v) return t[y].v-t[x].v;
int mid=(l+r)>>1;
if(v<=mid) return query(l,mid,t[x].l,t[y].l,v)+t[t[y].r].v-t[t[x].r].v;
else return query(mid+1,r,t[x].r,t[y].r,v);
}

int main()
{
n
=read(),m=read();q=read(),tt=read();
for(int i=0;i<=n;++i) val[i]=inf;
for(int i=1;i<=m;++i)
{
e[i].x
=read(),e[i].y=read();
val[n
+i]=i;tim[i]=m+1;
if(e[i].x==e[i].y){tim[i]=i;continue;}
link(e[i].x,e[i].y,n
+i);
}
for(int i=1;i<=m;++i)
build(
0,m+1,rt[i-1],rt[i],tim[i]);
for(int i=1,l,r;i<=q;++i)
{
l
=read(),r=read();
if(tt) l^=ans,r^=ans;
printf(
"%d\n",ans=n-query(0,m+1,rt[l-1],rt[r],r+1));
}
return 0;
}

 

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告