【BZOJ3514】— Codechef MARCH14 GERALD07加强版(LCT+主席树)
考虑按照编号依次把点加入
假设当前加入边,如果形成了环
将环上最小的边删去,并记
考虑一次询问
如果
那么边加进去就不会形成连通块
于是考虑统计满足这样的的个数
用主席树就完了
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
const int mod=998244353,g=3;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=400005;
namespace Lct{
int fa[N],son[N][2],mn[N],id[N],val[N],rev[N];
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline bool isrc(int u){
return rc(fa[u])==u;
}
inline bool isrt(int u){
return lc(fa[u])!=u&&rc(fa[u])!=u;
}
inline void pushup(int u){
id[u]=u,mn[u]=val[u];
if(lc(u)&&mn[lc(u)]<mn[u])mn[u]=mn[lc(u)],id[u]=id[lc(u)];
if(rc(u)&&mn[rc(u)]<mn[u])mn[u]=mn[rc(u)],id[u]=id[rc(u)];
}
inline void pushdown(int u){
if(!rev[u])return;
if(lc(u))rev[lc(u)]^=1;
if(rc(u))rev[rc(u)]^=1;
swap(lc(u),rc(u));
rev[u]=0;
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=rc(u)==v;
fa[v]=z;
if(!isrt(u))son[z][rc(z)==u]=v;
fa[son[v][t^1]]=u,son[u][t]=son[v][t^1];
son[v][t^1]=u,fa[u]=v;
pushup(u),pushup(v);
}
int stk[N],top;
inline void splay(int u){
stk[top=1]=u;
for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
for(int i=top;i;i--)pushdown(stk[i]);
while(!isrt(u)){
if(!isrt(fa[u]))
isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
rotate(u);
}
}
inline void access(int u){
for(int v=0;u;v=u,u=fa[u]){
splay(u),rc(u)=v;
if(v)fa[v]=u;
pushup(u);
}
}
inline void makert(int u){
access(u),splay(u),rev[u]^=1;
}
inline void link(int u,int v){
makert(u),splay(v),fa[u]=v,pushup(v);
}
inline void cut(int u,int v){
makert(u),access(v),splay(v);
lc(v)=fa[u]=0;pushup(v);
}
}
namespace Pt{
cs int M=N*25;
int tot,lc[M],rc[M],rt[N],siz[M];
#define mid ((l+r)>>1)
inline void insert(int r1,int &u,int l,int r,int p){
u=++tot;
siz[u]=siz[r1]+1,lc[u]=lc[r1],rc[u]=rc[r1];
if(l==r)return;
if(p<=mid)insert(lc[r1],lc[u],l,mid,p);
else insert(rc[r1],rc[u],mid+1,r,p);
}
inline int query(int u,int l,int r,int st,int des){
if(!u)return 0;
if(st<=l&&r<=des)return siz[u];
int res=0;
if(st<=mid)res+=query(lc[u],l,mid,st,des);
if(mid<des)res+=query(rc[u],mid+1,r,st,des);
return res;
}
}
int n,m,q,last,tp;
int f[N];
struct edge{
int u,v;
}e[N];
int fa[N];
inline int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
n=read(),m=read(),q=read(),tp=read();
for(int i=1;i<=n;i++)Lct::val[i]=1e9,fa[i]=i;
for(int i=1;i<=m;i++){
e[i].u=read(),e[i].v=read();
Lct::val[i+n]=i;
}
for(int i=1;i<=m;i++){
int u=e[i].u,v=e[i].v;
if(u==v){f[i]=i;continue;}
int f1=find(u),f2=find(v);
if(f1!=f2){
fa[f1]=f2,Lct::link(i+n,u),Lct::link(i+n,v);
}
else{
Lct::makert(u),Lct::access(v),Lct::splay(v);
int mpos=Lct::id[v]-n;f[i]=mpos;
Lct::cut(e[mpos].u,mpos+n),Lct::cut(e[mpos].v,mpos+n);
Lct::link(i+n,u),Lct::link(i+n,v);
}
}
for(int i=1;i<=m;i++)if(f[i])Pt::insert(Pt::rt[i-1],Pt::rt[i],1,m,f[i]);else Pt::rt[i]=Pt::rt[i-1];
while(q--){
int l=read()^(last*tp),r=read()^(last*tp);
int del=Pt::query(Pt::rt[r],1,m,l,r)-Pt::query(Pt::rt[l-1],1,m,l,r);
cout<<(last=(n-(r-l+1)+del))<<'\n';
}
}