• [POJ3237]Tree


    题目描述 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 Description

    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 Description

    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

    数据范围及提示 Data Size & Hint

     

    之前的一些废话:是时候准备会考了。。

    题解:树链剖分+线段树,其中tag[o]表示pushdown的时候儿子需不需要再次反转。

    代码:

    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<cstdio>
    using namespace std;
    typedef long long LL;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef pair<int,int> PII;
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    const int maxn=10010,oo=2147483647;
    int T,n,m,a,b,c,ce,es,first[maxn],deep[maxn],size[maxn],ms[maxn],fa[maxn],bl[maxn],id[maxn],Eid[maxn];
    int A[maxn],Max[maxn<<2],Min[maxn<<2],tag[maxn<<2];
    char s[5];
    struct Edge
    {
        int u,v,w,next;
        Edge() {}
        Edge(int _1,int _2,int _3,int _4):u(_1),v(_2),w(_3),next(_4) {}
    }e[maxn<<1];
    void addEdge(int a,int b,int c)
    {
        e[++ce]=Edge(a,b,c,first[a]);first[a]=ce;
        e[++ce]=Edge(b,a,c,first[b]);first[b]=ce;
    }
    void rev(int o){int a=Max[o];Max[o]=-Min[o];Min[o]=-a;}
    void pushdown(int l,int r,int o)
    {
        int mid=(l+r)>>1,lo=o<<1,ro=lo|1;    
        if(l==r || !tag[o])return;
        tag[o]=0;tag[lo]^=1;tag[ro]^=1;
        rev(lo);rev(ro); 
    }
    void pushup(int l,int r,int o)
    {
        int mid=(l+r)>>1,lo=o<<1,ro=lo|1;    
        Max[o]=max(Max[lo],Max[ro]);
        Min[o]=min(Min[lo],Min[ro]);
    }
    void build(int l,int r,int o)
    {
        int mid=(l+r)>>1,lo=o<<1,ro=lo|1;    
        if(l==r)
        {
            Max[o]=Min[o]=A[l]; 
            return;
        }
        build(l,mid,lo);build(mid+1,r,ro);
        pushup(l,r,o);
    }
    void update(int l,int r,int o,int a,int b)
    {
        int mid=(l+r)>>1,lo=o<<1,ro=lo|1;    
        if(l==r)
        {
            tag[o]=0;Min[o]=Max[o]=b;
            return;
        }
        pushdown(l,r,o);
        if(a>mid)update(mid+1,r,ro,a,b);
        else update(l,mid,lo,a,b);
        pushup(l,r,o);
    }
    void Negate(int l,int r,int o,int a,int b)
    {
        int mid=(l+r)>>1,lo=o<<1,ro=lo|1;    
        if(l==a && r==b)
        {
            tag[o]^=1;rev(o);
            return;
        }
        pushdown(l,r,o);
        if(b<=mid)Negate(l,mid,lo,a,b);
        else if(a>mid)Negate(mid+1,r,ro,a,b);
        else Negate(l,mid,lo,a,mid),Negate(mid+1,r,ro,mid+1,b);
        pushup(l,r,o);
    }
    int query(int l,int r,int o,int a,int b)
    {
        int mid=(l+r)>>1,lo=o<<1,ro=lo|1;    
        if(l==a && r==b)return Max[o];
        pushdown(l,r,o);
        if(b<=mid)return query(l,mid,lo,a,b);
        else if(a>mid)return query(mid+1,r,ro,a,b);
        else return max(query(l,mid,lo,a,mid),query(mid+1,r,ro,mid+1,b));
    }
    void dfs(int now,int pa)
    {
        size[now]=1;
        for(int i=first[now];i!=-1;i=e[i].next)
            if(e[i].v!=pa)
            {
                fa[e[i].v]=now;deep[e[i].v]=deep[now]+1;
                dfs(e[i].v,now);
                size[now]+=size[e[i].v];
                if(size[e[i].v]>size[ms[now]])ms[now]=e[i].v;
            }
    }
    void divide(int now,int chain)
    {
        id[now]=++es;bl[now]=chain;
        if(ms[now])divide(ms[now],chain);
        for(int i=first[now];i!=-1;i=e[i].next)
            if(e[i].v!=fa[now])
            {
                if(e[i].v!=ms[now])divide(e[i].v,e[i].v);
                Eid[(i+2)>>1]=e[i].v;A[id[e[i].v]]=e[i].w;
            }
    }
    int lca(int a,int b)
    {
        while(bl[a]!=bl[b])
        {
            if(deep[bl[a]]<deep[bl[b]])swap(a,b);
            a=fa[bl[a]];
        }
        return deep[a]<deep[b] ? a : b;
    }
    void change(int a,int b)
    {
        while(bl[a]!=bl[b])
        {
            if(deep[bl[a]]<deep[bl[b]])swap(a,b);
            Negate(1,n,1,id[bl[a]],id[a]);
            a=fa[bl[a]];
        }
        if(id[b]+1<=id[a])Negate(1,n,1,id[b]+1,id[a]);
    }
    int ask(int a,int b)
    {
        int ans=-oo;
        while(bl[a]!=bl[b])
        {
            if(deep[bl[a]]<deep[bl[b]])swap(a,b);
            ans=max(ans,query(1,n,1,id[bl[a]],id[a]));
            a=fa[bl[a]];
        }
        if(id[b]+1<=id[a])ans=max(ans,query(1,n,1,id[b]+1,id[a]));
        return ans;
    }
    int main()
    {
        T=read();
        while(T--)
        {
            mem(first,-1);mem(e,0);mem(fa,0);mem(deep,0);mem(size,0);mem(ms,0);mem(bl,0);mem(id,0);mem(Eid,0);
            mem(A,0);mem(Max,0);mem(Min,0);mem(tag,0);ce=-1;es=0;
            n=read();
            for(int i=1;i<n;i++)a=read(),b=read(),c=read(),addEdge(a,b,c);
            dfs(1,-1);divide(1,1);build(1,n,1);
            while(1)
            {
                scanf("%s",s);
                if(s[0]=='D')break;
                a=read();b=read();
                if(s[0]=='C')update(1,n,1,id[Eid[a]],b);
                if(s[0]=='N')
                {
                    int c=lca(a,b);
                    change(a,c);change(b,c);
                }
                if(s[0]=='Q')
                {
                    int c=lca(a,b);
                    printf("%d
    ",max(ask(a,c),ask(b,c)));
                }
            }
        }
        return 0;
    }
    View Code

    总结:线段树的细节一定要想明白再写,最好先把线形的写好,并且对拍无误再上树。

  • 相关阅读:
    RAC SCAN漂移
    clickhouse通过uuid创建表
    oracle rac新增监听器
    oracle 19c ocr备份更改路径
    Svn与Git的区别,为什么使用git?
    SQL Server事务的回滚
    存储过程详解
    SQL Server 触发器
    Sql Prompt 10下载安装破解图文教程
    TFS对软件项目的简单管理
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/7061054.html
Copyright © 2020-2023  润新知