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

很好的一道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;
}

你可能感兴趣的:(BZOJ3069: [Pa2011]Hard Choice 艰难的选择)