• AC日记——Tree poj 3237


    Tree
    Time Limit: 5000MS   Memory Limit: 131072K
    Total Submissions: 9233   Accepted: 2431

    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 ≤ 100,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

    Source

     
    思路:
      树剖边权转点权;
      边权赋值到边上深度较大的点;
      然后有个取反操作,就是相反数;
      我们记录max和min;
      每次取反交换max和min;
      然后乘以-1;
      轻松ac(不知道wa了多少次);
     
    来,上代码:
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define maxn 1000005
    
    using namespace std;
    
    struct TreeNodeType {
        int l,r,dis,dis_,mid,flag;
    };
    struct TreeNodeType tree[maxn<<2];
    
    struct EdgeType {
        int v,w,next;
    };
    struct EdgeType edge[maxn<<1];
    
    int u_[maxn],v_[maxn];
    int if_z,t,n,cnt,head[maxn],deep[maxn],f[maxn];
    int flag[maxn],top[maxn],size[maxn],dis[maxn],dis_[maxn];
    
    char Cget;
    
    inline void in(int &now)
    {
        now=0,if_z=1,Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
        now*=if_z;
    }
    
    inline void edge_add(int u,int v,int w)
    {
        edge[++cnt].v=v,edge[cnt].w=w,edge[cnt].next=head[u],head[u]=cnt;
        edge[++cnt].v=u,edge[cnt].w=w,edge[cnt].next=head[v],head[v]=cnt;
    }
    
    void search_1(int now,int fa)
    {
        int pos=cnt++;
        deep[now]=deep[fa]+1,f[now]=fa;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].v==fa) continue;
            dis_[edge[i].v]=edge[i].w;
            search_1(edge[i].v,now);
        }
        size[now]=cnt-pos;
    }
    
    void search_2(int now,int chain)
    {
        int pos=0;
        top[now]=chain;
        flag[now]=++cnt;
        dis[flag[now]]=dis_[now];
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].v==f[now]) continue;
            if(size[edge[i].v]>size[pos]) pos=edge[i].v;
        }
        if(pos==0) return ;
        search_2(pos,chain);
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].v==f[now]||edge[i].v==pos) continue;
            search_2(edge[i].v,edge[i].v);
        }
    }
    
    inline void tree_up(int now)
    {
        tree[now].dis=max(tree[now<<1].dis,tree[now<<1|1].dis);
        tree[now].dis_=min(tree[now<<1].dis_,tree[now<<1|1].dis_);
    }
    
    inline void tree_down(int now)
    {
        if(tree[now].l==tree[now].r) return ;
        tree[now<<1].dis*=-1,tree[now<<1|1].dis*=-1;
        tree[now<<1].dis_*=-1,tree[now<<1|1].dis_*=-1;
        tree[now<<1].flag*=-1,tree[now<<1|1].flag*=-1;
        swap(tree[now<<1].dis_,tree[now<<1].dis);
        swap(tree[now<<1|1].dis_,tree[now<<1|1].dis);
        tree[now].flag=1;return ;
    }
    
    void tree_build(int now,int l,int r)
    {
        tree[now].l=l,tree[now].r=r,tree[now].flag=1;
        if(l==r)
        {
            tree[now].dis=dis[l];
            tree[now].dis_=tree[now].dis;
            return ;
        }
        tree[now].mid=(l+r)>>1;
        tree_build(now<<1,l,tree[now].mid);
        tree_build(now<<1|1,tree[now].mid+1,r);
        tree_up(now);
    }
    
    void tree_change(int now,int to,int x)
    {
        if(tree[now].l==tree[now].r)
        {
            tree[now].dis=x;
            tree[now].dis_=x;
            return ;
        }
        if(tree[now].flag==-1) tree_down(now);
        if(to<=tree[now].mid) tree_change(now<<1,to,x);
        else tree_change(now<<1|1,to,x);
        tree_up(now);
    }
    
    void tree_negate(int now,int l,int r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            tree[now].dis*=-1;
            tree[now].dis_*=-1;
            swap(tree[now].dis,tree[now].dis_);
            tree[now].flag*=-1;
            return ;
        }
        if(tree[now].flag==-1) tree_down(now);
        if(l>tree[now].mid) tree_negate(now<<1|1,l,r);
        else if(r<=tree[now].mid) tree_negate(now<<1,l,r);
        else
        {
            tree_negate(now<<1,l,tree[now].mid);
            tree_negate(now<<1|1,tree[now].mid+1,r);
        }
        tree_up(now);
    }
    
    int tree_query(int now,int l,int r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            return tree[now].dis;
        }
        if(tree[now].flag==-1) tree_down(now);
        if(l>tree[now].mid) return tree_query(now<<1|1,l,r);
        else if(r<=tree[now].mid) return tree_query(now<<1,l,r);
        else
        {
            return max(tree_query(now<<1,l,tree[now].mid),tree_query(now<<1|1,tree[now].mid+1,r));
        }
    }
    
    int solve_query(int x,int y)
    {
        int pos=-0x7ffffff;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            pos=max(pos,tree_query(1,flag[top[x]],flag[x]));
            x=f[top[x]];
        }
        if(x==y) return pos;
        if(deep[x]>deep[y]) swap(x,y);
        pos=max(pos,tree_query(1,flag[x]+1,flag[y]));
        return pos;
    }
    
    void solve_negate(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            tree_negate(1,flag[top[x]],flag[x]);
            x=f[top[x]];
        }
        if(x==y) return ;
        if(deep[x]>deep[y]) swap(x,y);
        tree_negate(1,flag[x]+1,flag[y]);
    }
    
    int main()
    {
        in(t);
        while(t--)
        {
            memset(head,0,sizeof(head));
            in(n);cnt=0;
            int u,v,w;char ch[10];
            for(int i=1;i<n;i++)
            {
                in(u),in(v),in(w);
                u_[i]=u,v_[i]=v,edge_add(u,v,w);
            }
            cnt=0,search_1(1,0);
            cnt=0,search_2(1,1);
            tree_build(1,1,n);
            for(int i=1;i<n;i++)
            {
                if(deep[u_[i]]<deep[v_[i]]) swap(u_[i],v_[i]);
            }
            while(1)
            {
                cin>>ch;
                if(ch[0]=='D') break;
                in(u),in(v);
                if(ch[0]=='N') solve_negate(u,v);
                if(ch[0]=='C') tree_change(1,flag[u_[u]],v);
                if(ch[0]=='Q')
                {
                    cout<<solve_query(u,v);
                    putchar('
    ');
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Excel 相对引用与绝对引用
    SQL Update 巧用
    Delphi 多步操作产生错误,请检查每一步的状态值
    cxGrid 增加序号 (非数据库绑定模式) (测试通过)
    delphi cxgrid 使用方法
    如何使满足条件的数据显示不同的颜色
    Delphi中Format与FormatDateTime函数详解
    常用的日期时间函数
    100m和1000m网线的常见制作方法
    基于请求的分布式互斥算法
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6414757.html
Copyright © 2020-2023  润新知