BZOJ3069: [Pa2011]Hard Choice 艰难的选择

来源:互联网 发布:阿里云个人域名备案 编辑:程序博客网 时间:2024/05/16 11:36

很好的一道LCT的题目
虽然能马上发现时LCT但是这个性质起码我是画了个图。。。
要处在同一个强联通分量里的点才有两条不重合路径
那么很容易想出来只需要离线每次加边同时缩点就好了
然后只需要打个并查集维护一下当前点被缩成哪个点就好了
我第一次LCT的并查集忘了更新了

#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<map>using namespace std;char c;inline void read(int &a){    a=0;do c=getchar();while(c<'0'||c>'9');    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}struct Node{    Node *f,*lc,*rc;    Node *Replace;    int Rev;    Node(){Replace=this;}    inline bool H(){return f->lc==this||f->rc==this;}    inline bool l(){return f->lc==this;}}Place[100001],*empty;inline void Begin(){    empty=new Node;    empty->lc=empty->rc=empty->f=empty->Replace=empty;}Node*FFF(Node *a){return a->Replace=(a->Replace==a?(a):FFF(a->Replace));} inline void Rev(Node *a){    a->Rev^=1;    Node *l=a->lc;    a->lc=a->rc,a->rc=l;    a->rc->Rev^=1,a->lc->Rev^=1;}inline void Lc(Node*a){    Node *ne;    if(a->f->H())      if(a->f->l())         a->f->f->lc=a,ne=a->f->f;        else           a->f->f->rc=a,ne=a->f->f;    else if(a->f->f!=a->f)   ne=a->f->f;    else ne=a;    a->f->lc=a->rc;    a->rc->f=a->f;    a->rc=a->f;    a->f->f=a;    a->f=ne;}inline void Rc(Node*a){    Node *ne;    if(a->f->H())      if(a->f->l())         a->f->f->lc=a,ne=a->f->f;        else           a->f->f->rc=a,ne=a->f->f;    else if(a->f->f!=a->f)   ne=a->f->f;    else ne=a;    a->f->rc=a->lc;    a->lc->f=a->f;    a->lc=a->f;    a->f->f=a;    a->f=ne;}inline void Turn(Node *a){a->l()?Lc(a):Rc(a);}inline void Change(Node*a){if(a->f->Rev)Rev(a->f);if(a->Rev)Rev(a);Turn(a);}inline void TwiChange(Node*a){if(a->f->f->Rev)Rev(a->f->f);if(a->f->Rev)Rev(a->f);if(a->Rev)Rev(a);a->l()==a->f->l()?Turn(a->f):Turn(a);Turn(a);}inline void Splay(Node *a){    while(a->H()&&a->f->H())TwiChange(a);    while(a->H())Change(a);}inline void Access(Node *a){    if(a->Rev)Rev(a);    a->f=FFF(a->f);    while(true)     {        Splay(a);        a->f=FFF(a->f);        if(a->f==a)return;          Splay(a->f);        if(a->f->Rev)Rev(a->f);        a->f->rc=a;     }}inline void MakeRoot(Node *a){    Access(a);    a->lc->Rev^=1;    a->lc=empty;}inline void Split(Node *a,Node *b){    MakeRoot(a);    Access(b);    while(a->f!=b)Change(a);}void Del(Node*a,Node*Replace){    if(a==empty)return;    a->Replace=Replace;    Del(a->lc,Replace);    Del(a->rc,Replace);}inline void Ensmall(Node *a,Node *b){    Split(a,b);    a->lc->f=b;    b->lc=a->lc;    a->lc=empty;    Del(a,b);}struct Query{    int u,v;    int no;    bool del;    int ans;    inline friend bool operator <(Query a,Query b)    {return a.no>b.no;}}Q[100001];struct Side{     int u,v;     inline void So()     {if(u>v)swap(u,v);}     inline friend bool operator <(Side a,Side b)     {return a.u^b.u?a.u<b.u:a.v<b.v;} }L[100001];int F[100001];int find(int x){    return F[x]=(F[x]==x?x:find(F[x]));}inline void Link(Node *a,Node *b){    MakeRoot(a);    a->f=b;    Access(a);}map<Side,bool>D;int n,m,z;int main(){    int i,j,k;    Side tp;    Query t;    Begin();    read(n),read(m),read(z);    for(i=1;i<=n;i++)      Place[i].f=Place+i,Place[i].lc=empty,Place[i].rc=empty,Place[i].Rev=0,F[i]=i,Place[i].Replace=Place+i;    for(i=1;i<=m;i++)       read(tp.u),read(tp.v),tp.So(),D[tp]=true,L[i]=tp;    for(i=1;i<=z;i++)      {        do c=getchar();while(c!='Z'&&c!='P');        if(c=='Z')           {           read(t.u),read(t.v),           t.no=i;t.del=true;           Q[i]=t;           tp.u=t.u,tp.v=t.v;           tp.So();           D[tp]=false;          }          else           {           read(t.u),read(t.v),            t.no=i;t.del=false;            Q[i]=t;                   }      }     for(i=1;i<=m;i++)      if(D[L[i]])         {            if(FFF(Place+L[i].u)!=FFF(Place+L[i].v))               if(find(L[i].u)^find(L[i].v))                 F[find(L[i].u)]=F[L[i].v],Link(FFF(Place+L[i].u),FFF(Place+L[i].v));               else Ensmall(FFF(Place+L[i].u),FFF(Place+L[i].v));            else;          }    for(i=z;i;i--)    {       if(Q[i].del)              if(FFF(Place+Q[i].u)!=FFF(Place+Q[i].v))               if(find(Q[i].u)^find(Q[i].v))                 F[find(Q[i].u)]=F[Q[i].v],Link(FFF(Place+Q[i].u),FFF(Place+Q[i].v));               else Ensmall(FFF(Place+Q[i].u),FFF(Place+Q[i].v));               else;        else           Q[i].ans=FFF(Place+Q[i].u)==FFF(Place+Q[i].v);    }    for(i=1;i<=z;i++)      if(!Q[i].del)puts(Q[i].ans?"TAK":"NIE");    return 0;}
0 0