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

      

    也许有挫折,但这些,怎能挡住湘北前进的步伐
  • 相关阅读:
    nignx 配置https
    开发插件
    pdf 转word 网站
    github 镜像站点
    apk 托管
    系统引导原理以及过程
    网络维护-路由与路由的链接
    linux 常用命令
    Linux netsat 命令
    Oracle登录 ORA-01033: ORACLE正在初始化或关闭的解决方法
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2579461.html
Copyright © 2020-2023  润新知