bzoj3514 GERALD07

来源:互联网 发布:千兆网络测速工具 编辑:程序博客网 时间:2024/06/10 22:37

求出每个边加入后构成环弹出最早进来的那个边是什么,问题转化为求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;}


0 0