bzoj1180: [CROATIAN2009]OTOCI(lct)

来源:互联网 发布:unity3d与ar 编辑:程序博客网 时间:2024/06/08 10:13

Description

给出n个结点以及每个点初始时对应的权值wi。起始时点与点之间没有连边。有3类操作: 1、bridge A B:询问结点A与结点B是否连通。如果是则输出“no”。否则输出“yes”,并且在结点A和结点B之间连一条无向边。 2、penguins A X:将结点A对应的权值wA修改为X。 3、excursion A B:如果结点A和结点B不连通,则输出“impossible”。否则输出结点A到结点B的路径上的点对应的权值的和。给出q个操作,要求在线处理所有操作。数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

Input

第一行包含一个整数n(1<=n<=30000),表示节点的数目。第二行包含n个整数,第i个整数表示第i个节点初始时对应的权值。第三行包含一个整数q(1<=n<=300000),表示操作的数目。以下q行,每行包含一个操作,操作的类别见题目描述。任意时刻每个节点对应的权值都是1到1000的整数。

Output

输出所有bridge操作和excursion操作对应的输出,每个一行。

Sample Input

5
4 2 4 5 6
10
excursion 1 1
excursion 1 2
bridge 1 2
excursion 1 2
bridge 3 4
bridge 3 5
excursion 4 5
bridge 1 3
excursion 2 4
excursion 2 5

Sample Output

4
impossible
yes
6
yes
yes
15
yes
15
16

题解:动态树。
统计和时在access()和rotate()里面更新即可。

(三目运算符一定要加括号!!!!)

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;const int Maxn=3e4+50;inline ll read(){    char ch=getchar();int i=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}    return i*f;}struct node{    node *lc,*rc,*fa;    ll w,sum;    int tag;    node(const ll &v):lc(NULL),rc(NULL),fa(NULL),w(v),sum(v),tag(0){};    inline void upt()    {        sum=((lc?lc->sum:0)+(rc?rc->sum:0))+w;    }}*tr[Maxn];int n,Q;inline bool isroot(node *x){    return !x->fa||(x->fa->lc!=x&&x->fa->rc!=x);}inline void downdate(node *x){    if(x->tag)    {        swap(x->lc,x->rc);        if(x->lc)x->lc->tag^=1;        if(x->rc)x->rc->tag^=1;        x->tag=0;    }}inline void rotate(node *x){    node *y=x->fa,*z=y->fa;    if(z&&!isroot(y))    ((z->lc==y)?(z->lc):(z->rc))=x;    x->fa=z,y->fa=x;    node *b=y->lc==x?x->rc:x->lc;    b?b->fa=y:0;    if(y->lc==x)x->rc=y,y->lc=b;    else x->lc=y,y->rc=b;    y->upt(),x->upt();  }inline bool which(node *x){    return x->fa->lc==x;}inline void splay(node *x){    static node *que[Maxn];    int qn=0;    que[qn=1]=x;    for(node *y=x;!isroot(y);y=y->fa)que[++qn]=y->fa;    for(int i=qn;i>=1;i--)downdate(que[i]);    while(!isroot(x))    {        if(!isroot(x->fa))        {            if(which(x)^which(x->fa))rotate(x);            else rotate(x->fa);        }        rotate(x);    }}inline void access(node *x){    for(node *y=NULL;x;y=x,x=x->fa)    {        splay(x);x->rc=y;        if(y)y->fa=x;        x->upt();    }}inline void makeroot(node *x){    access(x);    splay(x);    x->tag^=1;}inline node* findroot(node *x){    access(x);splay(x);    while(x->lc)x=x->lc;    return x;}inline void link(node *x,node *y){    makeroot(x);    x->fa=y;}int main(){    n=read();    for(int i=1;i<=n;i++)    {        ll x=read();        tr[i]=new node(x);    }    Q=read();    while(Q--)    {        static char ch[20];        scanf("%s",ch+1);        if(ch[1]=='b')        {            int x=read(),y=read();            makeroot(tr[x]);            if(findroot(tr[y])==tr[x])puts("no");            else puts("yes"),link(tr[x],tr[y]);        }        else if(ch[1]=='p')        {            int x=read();            ll val=read();            makeroot(tr[x]);            tr[x]->w=val;            tr[x]->upt();        }        else        {            int x=read(),y=read();            makeroot(tr[x]);            if(findroot(tr[y])!=tr[x])puts("impossible");            else            {                makeroot(tr[x]);                access(tr[y]);                splay(tr[y]);                 printf("%lld\n",tr[y]->sum);            }        }    }    return 0;}
0 0
原创粉丝点击