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);
            }
        }
    }
}

  

也许有挫折,但这些,怎能挡住湘北前进的步伐
原文地址:https://www.cnblogs.com/Fatedayt/p/2579461.html