BZOJ2843: 极地旅行社

裸LCT

#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;

struct Node
{
   Node *lc,*rc,*f;
   int data;
   int sum;
   bool Rev;
   Node *pl;
   inline bool h(){return f->lc==this||f->rc==this;}
   inline bool l(){return f->lc==this;}
};
Node *empty;
inline void Begin(){empty=new Node;empty->data=0,empty->sum=0,empty->lc=empty->rc=empty;empty->Rev=0;}
inline Node *New_Node(){Node *tp=new Node;tp->data=0,tp->sum=0,tp->lc=empty;tp->rc=empty;tp->Rev=0;return tp;}
inline void updata(Node *a){a->sum=a->lc->sum+a->rc->sum+a->data;}
inline void Lc(Node *a)
{
    Node *newf;
    if(a->f->f==a->f)
        newf=a;
    else if(!a->f->h())
        newf=a->f->f;
    else if(a->f->l()) 
        newf=a->f->f,a->f->f->lc=a;
    else 
        newf=a->f->f,a->f->f->rc=a;
    a->rc->f=a->f;
    a->f->lc=a->rc;
    a->rc=a->f;
    a->f->f=a;
    a->f=newf;
    updata(a->rc);
    updata(a);
}
inline void Rev(Node *a)
{Node *tp=a->lc;a->lc=a->rc;a->rc=tp;a->lc->Rev^=1,a->rc->Rev^=1,a->Rev^=1;}
inline void Rc(Node *a)
{
    Node *newf;
    if(a->f->f==a->f)
        newf=a;
    else if(!a->f->h())
        newf=a->f->f;
    else if(a->f->l()) 
        newf=a->f->f,a->f->f->lc=a;
    else 
        newf=a->f->f,a->f->f->rc=a;
    a->lc->f=a->f;
    a->f->rc=a->lc;
    a->lc=a->f;
    a->f->f=a;
    a->f=newf;
    updata(a->lc);
    updata(a);
}
inline void Change(Node *a)
{a->l()?Lc(a):Rc(a);}
inline void Twice_Change(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()?Change(a->f):Change(a);Change(a);
}
inline void Once_Change(Node *a)
{
    if(a->f->Rev)Rev(a->f);
    if(a->Rev)Rev(a);
    Change(a);
}
inline void Splay(Node *a)
{
    while(a->f->h()&&a->h())Twice_Change(a);
    while(a->h())Once_Change(a);
}

inline void Access(Node *a)
{
    while(true){Splay(a);if(a->f==a)return;if(a->f->Rev)Rev(a->f);Splay(a->f);a->f->rc=a;}
}
inline void MakeRoot(Node *a)
{
      Access(a);
      a->lc->Rev^=1,a->lc=empty;
      updata(a);
}

int F[100001];
int find(int x){return F[x]=(F[x]==x?x:find(F[x]));}
inline void Union(int x,int y){F[find(x)]=F[find(y)];}

Node S[100001];
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();
}
int main()
{
    int n,m;
    read(n);
    Begin();
    for(int i=1;i<=n;i++)
      S[i].pl=S+i,F[i]=i,read(S[i].data),S[i].sum=S[i].data,S[i].f=&S[i],S[i].lc=empty,S[i].rc=empty;;
    read(m);
    int x,y;
    for(int i=1;i<=m;i++)
       {
        do c=getchar();while(c!='b'&&c!='e'&&c!='p');
        if(c=='b')
          {
            read(x),read(y);
            if(find(x)==find(y))puts("no");
            else puts("yes"),Union(x,y),MakeRoot(&S[x]),S[x].f=&S[y];
          }
        else if(c=='p')
           {
            read(x);
            read(S[x].data),MakeRoot(&S[x]);
           }
        else if(c=='e')
            {
                read(x),read(y);
                if(find(x)!=find(y))
                  puts("impossible");
                else
                   {
                    MakeRoot(&S[x]);
                    Access(&S[y]);
                    printf("%d\n",S[y].lc->sum+S[y].data);
                   }
            }

       }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值