zoukankan      html  css  js  c++  java
  • POJ3237 Tree(树剖+线段树+lazy标记)

    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

    题意:

    对于一棵树,有几种操作:

      Q :x y 。问x到y之间的路径的最大边权值为多少。

      C :x y。把第x条边的权值改为y。

      N:x y。把x到y之间的边权值取反。

      D。结束。

    思路:

     和前面一道树剖题的查询是一样的,所以同样需要树剖+线段树,对于C操作,同样是线段树单点更新即可。但是需要区间权值取反,得用lazy标记一下。记录最大和最小值,方便在取反后还能得到最大值。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    #define swap(a,b) (a^=b,b^=a,a^=b)
    using namespace std;
    const int maxn=200010;
    int Laxt[maxn],Next[maxn],To[maxn],e[maxn][3],cnt;
    int n,q; char opt[10];
    struct TreeCut
    {
        int dpt[maxn],top[maxn],son[maxn],fa[maxn],sz[maxn],tot;
        int tid[maxn],Rank[maxn],tim;
        int Max[maxn<<2],Min[maxn<<2],Lazy[maxn<<2];
        void init()
        {
            cnt=1; tim=0;
            memset(Laxt,0,sizeof(Laxt));
            memset(Max,0,sizeof(Max));
            memset(Min,0,sizeof(Min));
            memset(Lazy,0,sizeof(Lazy));
        }
        void add_edge(int u,int v)
        {
            Next[++cnt]=Laxt[u];
            Laxt[u]=cnt; To[cnt]=v;
        }
        void dfs1(int u,int pre)
        {
            fa[u]=pre;dpt[u]=dpt[pre]+1;sz[u]=1;son[u]=0;
            for(int i=Laxt[u];i;i=Next[i]){
                int v=To[i]; if(v==pre) continue;
                dfs1(v,u);sz[u]+=sz[v];
                if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
            }
        }
        void pushdown(int Now)
        {
             swap(Max[Now<<1],Min[Now<<1]),Max[Now<<1]=-Max[Now<<1],Min[Now<<1]=-Min[Now<<1];
             swap(Max[Now<<1|1],Min[Now<<1|1]),Max[Now<<1|1]=-Max[Now<<1|1],Min[Now<<1|1]=-Min[Now<<1|1]; 
             Lazy[Now<<1]^=1;Lazy[Now<<1|1]^=1;Lazy[Now]=0; 
        }
        void pushup(int Now)
        {
            Max[Now]=max(Max[Now<<1],Max[Now<<1|1]);
            Min[Now]=min(Min[Now<<1],Min[Now<<1|1]); 
        }
        void dfs2(int u,int Top)
        {
            top[u]=Top; tid[u]=tim++;Rank[tid[u]]=u;
            if(!son[u]) return ;  dfs2(son[u],Top);
            for(int i=Laxt[u];i;i=Next[i])
               if(To[i]!=fa[u]&&To[i]!=son[u])  dfs2(To[i],To[i]);
        }
        void update(int Now,int L,int R,int pos,int val)
        {
            if(L==R){ Max[Now]=Min[Now]=val; return; }
            if(Lazy[Now]&1) pushdown(Now);
            int Mid=(L+R)>>1;
            if(Mid>=pos) update(Now<<1,L,Mid,pos,val);
            else update(Now<<1|1,Mid+1,R,pos,val);
            pushup(Now);
        }    
        int getmax(int Now,int L,int R,int l,int r)
        {
            if(L>=l&&R<=r) return Max[Now];
            if(Lazy[Now]&1) pushdown(Now);
            int Mid=(L+R)>>1,ans=-0x7fffffff;
            if(r<=Mid) ans=getmax(Now<<1,L,Mid,l,r);
            else if(l>Mid) ans=getmax(Now<<1|1,Mid+1,R,l,r);
            else ans=max(getmax(Now<<1,L,Mid,l,Mid),getmax(Now<<1|1,Mid+1,R,Mid+1,r));
            pushup(Now); return ans; 
        }
        void addsign(int Now,int L,int R,int l,int r)
        {
            if(L>=l&&R<=r) {
                Lazy[Now]^=1;swap(Max[Now],Min[Now]);
                Max[Now]=-Max[Now];Min[Now]=-Min[Now];
                return ;
            }
            if(Lazy[Now]&1) pushdown(Now);
            int Mid=(L+R)>>1;
            if(l<=Mid) addsign(Now<<1,L,Mid,l,r);
            if(r>Mid)  addsign(Now<<1|1,Mid+1,R,l,r);
            pushup(Now);
        }
        void Make_Tree()
        {
            scanf("%d",&n);
            for(int i=1;i<n;i++){
                scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
                add_edge(e[i][0],e[i][1]);add_edge(e[i][1],e[i][0]);
            }  dfs1(1,0);  dfs2(1,1);
            for(int i=1;i<n;i++){
                if(dpt[e[i][1]]<dpt[e[i][0]])  swap(e[i][1],e[i][0]);
                update(1,1,n-1,tid[e[i][1]],e[i][2]);
            }
        }
        int query(int u,int v)
        {
            int f1=top[u],f2=top[v],ans=-0x7fffffff;
            while(f1!=f2){
               if(dpt[f1]<dpt[f2]) swap(f1,f2),swap(u,v);
               ans=max(ans,getmax(1,1,n-1,tid[f1],tid[u]));
               u=fa[f1]; f1=top[u];
            }
            if(u!=v){
                if(dpt[u]>dpt[v]) swap(u,v);
                ans=max(ans,getmax(1,1,n-1,tid[son[u]],tid[v]));
            } printf("%d
    ",ans);
        }
        int Add_lazy(int u,int v)
        {
            int f1=top[u],f2=top[v];
            while(f1!=f2){
               if(dpt[f1]<dpt[f2]) swap(f1,f2),swap(u,v);
               addsign(1,1,n-1,tid[f1],tid[u]);
               u=fa[f1]; f1=top[u];
            }
            if(u!=v){
                if(dpt[u]>dpt[v]) swap(u,v);
                addsign(1,1,n-1,tid[son[u]],tid[v]);
            }
        }
        void Query()
        {
            while(~scanf("%s",opt)) { 
                if(opt[0]=='D') return;
                int x,y; scanf("%d%d",&x,&y);
                if(opt[0]=='Q') query(x,y);
                else if(opt[0]=='N') Add_lazy(x,y);
                else update(1,1,n-1,tid[e[x][1]],y);
            }
        }
    }Tc;
    int main()
    {
        int T; scanf("%d",&T);
        while(T--) {
             Tc.init();  
             Tc.Make_Tree();
             Tc.Query();
        }  return 0;
    }
  • 相关阅读:
    关于unicode编码问题——[ASIS 2019]Unicorn shop
    cve-2020-7066 ssrf漏洞——GKCTF2020
    updatexml()报错注入——[极客大挑战 2019]HardSQL
    用户名和密码分开检验产生的mysql注入——[GXYCTF2019]BabySQli
    安恒月赛——Ezunserialize(反序列化字符逃逸)
    记一次Flask模板注入学习 [GYCTF2020]FlaskApp
    [CISCN2019 华北赛区 Day2 Web1]Hack World
    [SUCTF 2019]CheckIn(user.ini文件构成的php后门)
    sql注入用<>绕过被过滤的select ——百度杯9月第二场SQL
    剑指offer32 从上到下打印二叉树(叁)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8080872.html
Copyright © 2011-2022 走看看