POJ3237 Tree

POJ3237 Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 2158   Accepted: 574

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers ab and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1



3

1 2 1

2 3 2

QUERY 1 2

CHANGE 1 3

QUERY 1 2

DONE

Sample Output

1

3
-------------------------------------------------------------
题目大意:指定一颗树上有3个操作:询问操作,询问a点和b点之间的路径上最长的那条边的长度;取反操作,将a点和b点之间的路径权值都取相反数;变化操作,把某条边的权值变成指定的值。
解体思路:这个思路很明显的路径剖分,完全就是来练写路径剖分的。路径剖分讲的比较好的:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
     就是从来没写过,写得蛋疼,洋洋洒洒5400B,代码风格全然丧失,还好没有出大错误,不然改都没法改。
#include <stdio.h>

#include <string.h>

#include <iostream>

#define clr(a,b) memset(a,b,sizeof(a))

using namespace std;



const int N=10005,M=60005,inf=0x3f3f3f3f;

int n,eid,head[N],ed[N<<1],val[N<<1],nxt[N<<1];

int fa[N],top[N],dep[N],siz[N],id[N],son[N],nid,w[N],p[N];

int le[M],ri[M],rate[M],lazy[M],flag[M],minn[M],maxx[M];

char s[10];



void addedge(int s,int e,int v){

    ed[eid]=e;val[eid]=v;nxt[eid]=head[s];head[s]=eid++;

}



/*第一次dfs,确定dep,siz,son,fa*/

void dfs1(int s,int f,int d){

    fa[s]=f;dep[s]=d;siz[s]=1;son[s]=-1;

    for(int i=head[s];~i;i=nxt[i]){

        int e=ed[i];if(e==f)continue;

        dfs1(e,s,d+1);siz[s]+=siz[e];p[e]=i;

        if(son[s]==-1||siz[e]>siz[son[s]])son[s]=e;

    }

}



/*第二次dfs,确定每条边在线段树中的位置(其实只要重边在线段树

里面就好了,但是为了写代码方便,就把所有的边加到线段树了,但保证

了重链是在一起的)*/

void dfs2(int s,int f){

    id[s]=++nid;if(~p[s])w[nid]=val[p[s]];

    if(!top[s])top[s]=s;

    if(~son[s]){top[son[s]]=top[s];dfs2(son[s],s);}

    for(int i=head[s];~i;i=nxt[i])

        if(ed[i]!=f&&ed[i]!=son[s])dfs2(ed[i],s);

}



void build(int l,int r,int rt){

    le[rt]=l;ri[rt]=r;int mid=(l+r)>>1;

    rate[rt]=1;lazy[rt]=flag[rt]=0;

    if(l==r){

        maxx[rt]=minn[rt]=w[l];return ;

    }

    build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);

    minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);

    maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);

}



void update(int l,int r,int rt,int a,int b,int c){

    if(l==le[rt]&&r==ri[rt]){

        if(a==-1){

            int k=maxx[rt];maxx[rt]=-minn[rt];

            minn[rt]=-k;rate[rt]*=-1;lazy[rt]=-lazy[rt];

        }

        if(c)lazy[rt]=maxx[rt]=minn[rt]=0;

        lazy[rt]+=b;flag[rt]=1;

        maxx[rt]+=b;minn[rt]+=b;

        return ;

    }

    if(le[rt]==ri[rt])return ;

    int mid=(le[rt]+ri[rt])>>1;

    if(flag[rt]){

        update(le[rt],mid,rt<<1,rate[rt],lazy[rt],0);

        update(mid+1,ri[rt],rt<<1|1,rate[rt],lazy[rt],0);

        rate[rt]=1;lazy[rt]=flag[rt]=0;

    }

    if(r<=mid)update(l,r,rt<<1,a,b,c);

    else if(l>mid)update(l,r,rt<<1|1,a,b,c);

    else{

        update(l,mid,rt<<1,a,b,c);update(mid+1,r,rt<<1|1,a,b,c);

    }

    minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);

    maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);

}



int query(int l,int r,int rt,int a,int b){

    if(l==le[rt]&&r==ri[rt])return max(maxx[rt]*a,minn[rt]*a)+b;

    int mid=(le[rt]+ri[rt])>>1;

    b+=lazy[rt]*a;a*=rate[rt];

    if(r<=mid)return query(l,r,rt<<1,a,b);

    else if(l>mid)return query(l,r,rt<<1|1,a,b);

    return max(query(l,mid,rt<<1,a,b),query(mid+1,r,rt<<1|1,a,b));

}



int main(){

//    freopen("/home/axorb/in","r",stdin);

    int T;scanf("%d",&T);

    while(T--){

        eid=0;clr(head,-1);

        scanf("%d",&n);

        for(int i=1;i<n;i++){

            int a,b,c;scanf("%d%d%d",&a,&b,&c);

            addedge(a,b,c);addedge(b,a,c);

        }

        p[1]=-1;dfs1(1,1,1);

        nid=-1;clr(top,0);dfs2(1,1);

        build(1,nid,1);

        while(scanf("%s",s),s[0]!='D'){

            int a,b;scanf("%d%d",&a,&b);

            if(s[0]=='N'){

                while(a!=b){

                    int f1=top[a],f2=top[b];

                    if(f1!=f2){

                        if(dep[f1]>dep[f2]){

                            if(f1==a)update(id[f1],id[f1],1,-1,0,0),a=fa[a];

                            else update(id[f1]+1,id[a],1,-1,0,0),a=f1;

                        }

                        else{

                            if(f2==b)update(id[f2],id[f2],1,-1,0,0),b=fa[b];

                            else update(id[f2]+1,id[b],1,-1,0,0),b=f2;

                        }

                    }

                    else{

                        if(dep[a]>dep[b])update(id[b]+1,id[a],1,-1,0,0);

                        else update(id[a]+1,id[b],1,-1,0,0);

                        a=b;

                    }

                }

            }

            else if(s[0]=='C'){

                a=(a-1)<<1;

                if(p[ed[a]]!=a)a^=1;

                update(id[ed[a]],id[ed[a]],1,1,b,1);

            }

            else{

                int maxx=-inf;

                while(a!=b){

                    int f1=top[a],f2=top[b];

                    if(f1!=f2){

                        if(dep[f1]>dep[f2]){

                            if(f1==a){

                                maxx=max(maxx,query(id[f1],id[f1],1,1,0));

                                a=fa[a];

                            }

                            else{

                                maxx=max(maxx,query(id[f1]+1,id[a],1,1,0));

                                a=f1;

                            }

                        }

                        else{

                            if(f2==b){

                                maxx=max(maxx,query(id[f2],id[f2],1,1,0));

                                b=fa[b];

                            }

                            else {

                                maxx=max(maxx,query(id[f2]+1,id[b],1,1,0));

                                b=f2;

                            }

                        }

                    }

                    else{

                        if(dep[a]>dep[b])maxx=max(maxx,query(id[b]+1,id[a],1,1,0));

                        else maxx=max(maxx,query(id[a]+1,id[b],1,1,0));

                        a=b;

                    }

                }

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

            }

        }

    }

}

  

你可能感兴趣的:(tree)