zoukankan      html  css  js  c++  java
  • poj3237 树链部分 边权模板

    Tree
    Time Limit: 5000MS   Memory Limit: 131072K
    Total Submissions: 7384   Accepted: 2001

    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
    /*
    poj3237 树链部分
    感觉是比较不错的题目,主要是线段树掌握不怎么好导致一直有问题。
    查询最大值 + 修改边 + 区间置反
    先处理出树链,然后再上值
    push_up 和 push_down函数
    hhh-2016-2-2 3:46:58
    */
    
    #include <functional>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <Map>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    
    using namespace std;
    
    const int maxn = 100010;
    
    struct node
    {
        int to,next;
    } edge[maxn*2];
    
    int head[maxn];
    int top[maxn];  //链的顶端节点
    int far[maxn];  //父亲
    int dep[maxn];  //深度
    int num[maxn];  //表示以x为根的子树的节点数
    int p[maxn];    //p[u]表示边u所在的位置
    int fp[maxn];   //与p相对应
    int son[maxn];  //重儿子
    int tot,pos;
    void addedge(int u,int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot ++;
    }
    
    void dfs(int u,int fa,int d)          //先处理出重儿子、dep、far、num
    {
        dep[u] = d;
        far[u] = fa;
        num[u] = 1;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(v != fa)
            {
                dfs(v,u,d+1);
                num[u] += num[v];
                if(son[u] == -1 || num[v] > num[son[u]])
                    son[u] = v;
            }
        }
    }
    
    void getpos(int u,int sp)
    {
        top[u] = sp;
        p[u] = pos++;
        fp[p[u]] = u;
        if(son[u] == -1) return ;
        getpos(son[u],sp);
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(v != far[u] && v != son[u])
                getpos(v,v);
        }
    }
    
    struct Node
    {
        int l,r;
        int flag;
        int Max,Min;
    } segtree[maxn*3];
    
    void build(int i,int l,int r)
    {
        segtree[i].l = l;
        segtree[i].r = r;
        segtree[i].Max = 0;
        segtree[i].Min = 0;
        segtree[i].flag = 0;
        if(l == r)
            return ;
        int mid = (l+r)/2;
        build(i<<1,l,mid);
        build((i<<1)|1,mid+1,r);
    }
    
    void push_up(int i)
    {
        segtree[i].Max = max(segtree[i<<1].Max,segtree[(i<<1)|1].Max);
        segtree[i].Min = min(segtree[i<<1].Min,segtree[(i<<1)|1].Min);
    }
    
    void push_down(int i)
    {
        if(segtree[i].l == segtree[i].r)
            return ;
        if(segtree[i].flag)
        {
            segtree[i<<1].Max = -segtree[i<<1].Max;
            segtree[i<<1].Min = -segtree[i<<1].Min;
            swap(segtree[i<<1].Max,segtree[i<<1].Min);
            segtree[i<<1].flag ^= 1;
    
            segtree[(i<<1)|1].Max = -segtree[(i<<1)|1].Max;
            segtree[(i<<1)|1].Min = -segtree[(i<<1)|1].Min;
            segtree[(i<<1)|1].flag ^= 1;
            swap(segtree[(i<<1)|1].Max,segtree[(i<<1)|1].Min);
    
            segtree[i].flag = 0;
        }
    }
    
    void update(int i,int k,int val)
    {
        if(segtree[i].l == k && segtree[i].r == k)
        {
            segtree[i].Max = val;
            segtree[i].Min = val;
            segtree[i].flag = 0;
            return ;
        }
        push_down(i);
        int mid = (segtree[i].l+segtree[i].r)>>1;
        if(k <= mid) update(i<<1,k,val);
        else update((i<<1)|1,k,val);
        push_up(i);
    }
    
    void negat(int i,int l,int r)
    {
        if((segtree[i].l == l && segtree[i].r == r))
        {
            segtree[i].Max = -segtree[i].Max;
            segtree[i].Min = -segtree[i].Min;
            swap(segtree[i].Max,segtree[i].Min);
            segtree[i].flag ^= 1;
            return;
        }
        push_down(i);
        int mid = (segtree[i].l+segtree[i].r)>>1;
        if(r <= mid) negat(i<<1,l,r);
        else if(l > mid) negat((i<<1)|1,l,r);
        else
        {
            negat(i<<1,l,mid);
            negat((i<<1)|1,mid+1,r);
        }
        push_up(i);
    }
    
    int query(int i,int l,int r)
    {
        if(segtree[i].l == l && segtree[i].r == r)
        {
            return segtree[i].Max;
        }
        push_down(i);
        int mid = (segtree[i].l+segtree[i].r)>>1;
        if(r <= mid) return query(i<<1,l,r);
        else if(l > mid) return query((i<<1)|1,l,r);
        else return max(query(i<<1,l,mid),query((i<<1)|1,mid+1,r));
        push_up(i);
    }
    
    int fin(int l,int r)
    {
        int f1 = top[l];
        int f2 = top[r];
        int tt = -100000000;
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1,f2);
                swap(l,r);
            }
            tt = max(query(1,p[f1],p[l]),tt);
            l = far[f1];
            f1 = top[l];
        }
        if(l == r)
            return tt;
        if(dep[l] > dep[r]) swap(l,r);
        return max(tt,query(1,p[son[l]],p[r]));
    }
    
    void change(int l,int r)
    {
        int f1 = top[l];
        int f2 = top[r];
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1,f2);
                swap(l,r);
            }
            negat(1,p[f1],p[l]);
            l = far[f1];
            f1 = top[l];
        }
        if(l == r) return ;
        if(dep[l] > dep[r]) swap(l,r);
        negat(1,p[son[l]],p[r]);
    }
    
    void ini()
    {
        tot = 0;
        pos = 1;
        memset(head,-1,sizeof(head));
        memset(son,-1,sizeof(son));
    }
    
    int me[maxn][2];
    int va[maxn];
    
    int main()
    {
        int T;
        int n;
        //freopen("in.txt","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            ini();
            for(int i = 1; i < n; i++)
            {
                scanf("%d%d%d",&me[i][0],&me[i][1],&va[i]);
                addedge(me[i][0],me[i][1]);
                addedge(me[i][1],me[i][0]);
            }
    
            dfs(1,0,0);
            getpos(1,1);
            build(1,1,n);
            for(int i = 1; i < n; i++)
            {
                if(dep[me[i][0]] > dep[me[i][1]])
                    swap(me[i][0],me[i][1]);
                update(1,p[me[i][1]],va[i]);
            }
            char ch[10];
            while(scanf("%s",ch) == 1)
            {
                ;
                if(ch[0] == 'D') break;
                int u,v;
                scanf("%d%d",&u,&v);
                if(ch[0] == 'Q')
                    printf("%d
    ",fin(u,v));
                else if(ch[0] == 'N')
                    change(u,v);
                else
                    update(1,p[me[u][1]],v);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    spring boot使用自定义注解+AOP实现对Controller层指定方法的日志记录
    spring事务管理中,注解方式和xml配置方式优先级谁高?
    synchronized修饰类中不同方法,调用的时候方法互斥吗
    java(spring boot)实现二维码生成(可以插入中间log和底部文字)
    java借助Robot给微信好友自动发消息(可发送表情包)
    js中Map类型的使用
    【转】Intellij笔记
    Tomcat6.0webappsevopWEB-INFclasses (系统找不到指定的路径)
    多线程多进程之其他
    文件操作
  • 原文地址:https://www.cnblogs.com/Przz/p/5409629.html
Copyright © 2011-2022 走看看