SPOJ 375 Query on a tree(动态树)

题目链接:http://www.spoj.com/problems/QTREE/

题意:给出一棵树,每条边有一个权值。两种操作:(1)修改某条边的权值;(2)询问某两个点之间路径权值的最大值?

思路:节点存储到父节点的权值以及该节点子树的最大值。

 
   






const int N=20005;



struct node

{

    int cost,maxcost,isRoot;

    node *c[2],*f;

};



node a[N],*nullNode;

int n,m,t,dy[N];



void up(node *p)

{

    p->maxcost=p->cost;

    if(p->c[0]->maxcost>p->maxcost) p->maxcost=p->c[0]->maxcost;

    if(p->c[1]->maxcost>p->maxcost) p->maxcost=p->c[1]->maxcost;

}



void rotate(node *p,int k)

{

    node *q=p->f;

    q->c[k]=p->c[!k];

    p->c[!k]->f=q;

    p->c[!k]=q;

    p->f=q->f;

    if(p->f->c[0]==q) p->f->c[0]=p;

    if(p->f->c[1]==q) p->f->c[1]=p;

    q->f=p;

    up(q);

    p->isRoot=q->isRoot;

    q->isRoot=0;

 }



void splay(node *p)

 {

     while (!p->isRoot)

     {

         if (p->f->isRoot)

         {

             if (p==p->f->c[0]) rotate(p,0);

             else rotate(p,1);

         }

         else

         {

             if (p->f->f->c[0]==p->f)

             {

                 if (p->f->c[0]==p) rotate(p->f,0);

                 else rotate(p,1);

                 rotate(p,0);

             }

             else

             {

                 if (p->f->c[1]==p) rotate(p->f,1);

                 else rotate(p,0);

                 rotate(p,1);

             }

         }

     }

     up(p);

}



node* access(node *p)

{

    node *t=p;

    node *q=nullNode;

    int ans;

    while(p!=nullNode)

    {

        splay(p);

        p->c[1]->isRoot=1;

        p->c[1]=q;

        q->isRoot=0;

        up(p);

        q=p;

        p=p->f;

    }

    return q;

}





void change(int t,int cost)

 {

     node *p=a+dy[t];

     access(p);

     p->cost=cost;

     up(p);

 }



void query(int x,int y)

{

    access(a+x);

    node *lca=access(a+y);

    splay(a+x);

    int ans=lca->c[1]->maxcost;

    if(lca!=a+x) ans=max(ans,a[x].maxcost);

    printf("%d\n",ans);

}





struct Node

{

    int v,dis,id,next;

};



Node edges[N];

int head[N],e;





void Add(int u,int v,int dis,int id)

{

    edges[e].v=v;

    edges[e].dis=dis;

    edges[e].id=id;

    edges[e].next=head[u];

    head[u]=e++;



    edges[e].v=u;

    edges[e].dis=dis;

    edges[e].id=id;

    edges[e].next=head[v];

    head[v]=e++;

}



void build(int u)

{

    int i,v;

    for(i=head[u];i!=-1;i=edges[i].next)

    {

        v=edges[i].v;

        if(a+v==a[u].f) continue;

        a[v].f=a+u;

        a[v].cost=a[v].maxcost=edges[i].dis;

        dy[edges[i].id]=v;

        build(v);

    }

}





int get()

{

    int x=0,flag=1;

    char c=getchar();

    while(!isdigit(c)) c=getchar();

    if(c=='-')

    {

        flag=-1,c=getchar();

        while(!isdigit(c)) c=getchar();

    }

    while(isdigit(c))

    {

        x=x*10+c-'0';

        c=getchar();

    }

    return x*flag;

}



void init()

{

    nullNode=a+10002;

    nullNode->c[0]=nullNode->c[1]=nullNode->f=nullNode;

    nullNode->maxcost=nullNode->cost=-1e9;

    n=get();

    int i,u,v,dis;

    FOR1(i,n)

    {

        a[i].c[0]=a[i].c[1]=a[i].f=nullNode;

        a[i].isRoot=1;

        a[i].maxcost=-1e9;a[i].cost=-1e9;

    }

    clr(head,-1);

    e=0;

    FOR1(i,n-1)

    {

        u=get();

        v=get();

        dis=get();

        Add(u,v,dis,i);

    }

    build(n);

}



int main()

{

    int C=get();

    while(C--)

    {

        init();

        char op[10];

        int a,b;

        while(1)

        {

            scanf("%s",op);

            if(op[0]=='D') break;

            a=get();

            b=get();

            if(op[0]=='Q') query(a,b);

            else change(a,b);

        }

    }

    return 0;

 }

 
   

  

 
  

你可能感兴趣的:(query)