求出每个边加入后构成环弹出最早进来的那个边是什么,问题转化为求l-r中那个值小于l的个数num,答案为n-num
LCT+主席树可以做。。。
/**************************************************************
Problem: 3514
User: Clare
Language: C++
Result: Accepted
Time:33684 ms
Memory:62604 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
#define N 400010
#define INF 0x7fffffff
int n,m,K,tot,type,Ans;
int fa[N],c[N][2],Min[N],v[N],smg[N],A[N][2];
struct Node{
int L,R;
int sum;
}t[N*10];
int root[N];
bool Rev[N];
stack<int> st;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void Updata(int &i,int l,int r,int val)
{
t[++tot]=t[i];i=tot;
t[i].sum++;
if(l==r)
return;
int mid=(l+r)/2;
if(val<=mid)
Updata(t[i].L,l,mid,val);
else Updata(t[i].R,mid+1,r,val);
}
int Query(int i,int j,int l,int r,int val)
{
if(l==r)
{
return t[i].sum-t[j].sum;
}
int mid=(l+r)/2;
if(val<=mid)
return Query(t[i].L,t[j].L,l,mid,val);
else return t[t[i].L].sum-t[t[j].L].sum+Query(t[i].R,t[j].R,mid+1,r,val);
}
bool Pd_root(int k)
{
return !(c[fa[k]][0]==k)&&!(c[fa[k]][1]==k);
}
void Pushup(int k)
{
int l=c[k][0],r=c[k][1];
Min[k]=k;
if(v[Min[k]]>v[Min[l]])Min[k]=Min[l];
if(v[Min[k]]>v[Min[r]])Min[k]=Min[r];
}
void Pushdown(int k)
{
int l=c[k][0],r=c[k][1];
if(Rev[k])
{
Rev[k]^=1;Rev[l]^=1;Rev[r]^=1;
swap(c[k][0],c[k][1]);
}
}
void Rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if(c[y][0]==x)l=0;else l=1;
r=l^1;
if(Pd_root(y));
else if(c[z][0]==y)c[z][0]=x;
else c[z][1]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
Pushup(y);Pushup(x);
}
void Splay(int x)
{
int i;
for(i=x;!Pd_root(i);i=fa[i])
st.push(i);
st.push(i);
while(!st.empty())
{
int now=st.top();st.pop();
Pushdown(now);
}
while(!Pd_root(x))
{
int y=fa[x],z=fa[y];
if(!Pd_root(y))
{
if(c[z][0]==y^c[y][0]==x)
Rotate(x);
else Rotate(y);
}
Rotate(x);
}
}
void Access(int x)
{
for(int t=0;x;t=x,x=fa[x])
Splay(x),c[x][1]=t,Pushup(x);
}
void Move_to_root(int x)
{
Access(x);Splay(x);Rev[x]^=1;
}
void Join(int x,int y)
{
Move_to_root(x);fa[x]=y;Pushup(x);
}
void Cut(int x,int y)
{
Move_to_root(x);Access(y);Splay(y);
if(c[y][0]==x)
c[y][0]=fa[x]=0;
else c[y][1]=fa[x]=0;
Pushup(y);Pushup(x);
}
int Find_root(int x)
{
Access(x);Splay(x);
while(c[x][0])
x=c[x][0];
return x;
}
void Split(int x,int y)
{
Move_to_root(x);Access(y);Splay(y);
}
int main()
{
n=read();m=read();K=read();type=read();
Min[0]=0;v[0]=INF;
for(int i=1;i<=n;i++)
Min[i]=i,v[i]=INF;
for(int i=1;i<=m;i++)
{
A[i][0]=read();A[i][1]=read();
if(A[i][0]==A[i][1])
{
smg[i]=i;continue;
}
v[i+n]=i;Min[i+n]=i+n;
if(Find_root(A[i][0])==Find_root(A[i][1]))
{
Split(A[i][0],A[i][1]);
int t=Min[A[i][1]];smg[i]=v[t];
Cut(t,A[t-n][0]);Cut(t,A[t-n][1]);
Join(i+n,A[i][0]);Join(i+n,A[i][1]);
}
else
{
smg[i]=0;
Join(i+n,A[i][0]);Join(i+n,A[i][1]);
}
}
for(int i=1;i<=m;i++)
{
root[i]=root[i-1];
Updata(root[i],1,200000,smg[i]+1);
}
for(int i=1;i<=K;i++)
{
int l=read(),r=read();
if(type)
{
l=l^Ans;r=r^Ans;
}
if(l>r)
Ans=0;
else
Ans=n-Query(root[r],root[l-1],1,200000,l);
printf("%d\n",Ans);
}
return 0;
}