• cogs1583. [POJ3237]树的维护


    1583. [POJ3237]树的维护

    http://www.cogs.pro/cogs/problem/problem.php?pid=1583

    ★★★☆   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比
    时间限制:5 s   内存限制:128 MB

    【题目描述】

    给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:

    CHANGE i v:将第i条边的权值改成v。

    NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。

    QUERY a b:找出点a到点b路径上各边的最大权值。

    【输入格式】

    输入文件的第一行有一个整数N(N<=10000)。

    接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。

    接下来是若干条指令(不超过10^5条),都按照上面所说的格式。

    输入文件的最后一行是"DONE".

    【输出格式】

    对每个“QUERY”指令,输出一行,即路径上各边的最大权值。

    【样例输入】

    3

    1 2 1

    2 3 2

    QUERY 1 2

    CHANGE 1 3

    QUERY 1 2

    DONE

    【样例输出】

    1

    3

    【提示】

    这里的输入输出格式和POJ上原题略有不同。

    【来源】

    POJ 3237 Tree

    难点在于取相反数操作

    记录下最大值和最小值,有取相反数操作时,就把两个值变成相反数,再交换两数的值就ok,然后给这个区间打上标记(线段树的lazy标记),以后访问或更改值时记得下传标记就好。

    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
     
    const int MAXN = 100010;
    struct Edge{
        int to,next;
    }edge[MAXN*2];
    int head[MAXN],tot;
    int top[MAXN];//top[v]表示v所在的重链的顶端节点 
    int fa[MAXN]; //父亲节点 
    int deep[MAXN];//深度 
    int num[MAXN];//num[v]表示以v为根的子树的节点数 
    int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置 
    int fp[MAXN];//和p数组相反 
    int son[MAXN];//重儿子 
    int pos;
    void init(){
        tot = 0;
        memset(head,-1,sizeof(head));
        pos = 0;
        memset(son,-1,sizeof(son));
    }
    void addedge(int u,int v){
        edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
    }
    void dfs1(int u,int v,int d){
        deep[v]=d;
        fa[v]=u;
        num[v]=1;
        for(int i=head[v];i!=-1;i=edge[i].next){
            int to=edge[i].to;
            if(to==u)continue;
            dfs1(v,to,d+1);
            num[v]+=num[to];
            if(son[v]==-1||num[son[v]]<num[to])son[v]=to;
        }
    }
    void dfs2(int u,int v){
        top[u]=v;
        p[u]=pos++;
        if(son[u]==-1)return;
        dfs2(son[u],v);
        for(int i=head[u];i!=-1;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa[u]||to==son[u])continue;
            dfs2(to,to);
        }
    }
     
    //线段树 
    struct Node{
        int l,r;
        int Max;
        int Min;
        int ne;
    }tr[MAXN*3];
    void build(int i,int l,int r){
        tr[i].l = l;
        tr[i].r = r;
        tr[i].Max = 0;
        tr[i].Min = 0;
        tr[i].ne = 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)
    {
        tr[i].Max = max(tr[i<<1].Max,tr[(i<<1)|1].Max);
        tr[i].Min = min(tr[i<<1].Min,tr[(i<<1)|1].Min);
    }
    void push_down(int i){
     
        if(tr[i].l == tr[i].r)return;
        if(tr[i].ne)
        {
            tr[i<<1].Max = -tr[i<<1].Max;
            tr[i<<1].Min = -tr[i<<1].Min;
            swap(tr[i<<1].Min,tr[i<<1].Max);
            tr[(i<<1)|1].Max = -tr[(i<<1)|1].Max;
            tr[(i<<1)|1].Min = -tr[(i<<1)|1].Min;
            swap(tr[(i<<1)|1].Max,tr[(i<<1)|1].Min);
            tr[i<<1].ne ^= 1;
            tr[(i<<1)|1].ne ^= 1;
            tr[i].ne = 0;
        }
    }
    void update(int i,int k,int val){ // 更新线段树的第k个值为val
     
        if(tr[i].l == k && tr[i].r == k)
        {
            tr[i].Max = val;
            tr[i].Min = val;
            tr[i].ne = 0;
            return;
        }
        push_down(i);
        int mid = (tr[i].l + tr[i].r)/2;
        if(k <= mid)update(i<<1,k,val);
        else update((i<<1)|1,k,val);
        push_up(i);
    }
     
    void ne_update(int i,int l,int r){
        if(tr[i].l==l&&tr[i].r==r){
            tr[i].Max=-tr[i].Max;tr[i].Min=-tr[i].Min;
            swap(tr[i].Max,tr[i].Min);
            tr[i].ne^=1;return;
        }
        push_down(i);
        int mid=(tr[i].l+tr[i].r)>>1;
        if(r<=mid)ne_update(i<<1,l,r);
        else if(l>mid)ne_update((i<<1)|1,l,r);
        else ne_update(i<<1,l,mid),ne_update((i<<1)|1,mid+1,r);
        tr[i].Min=min(tr[i<<1].Min,tr[(i<<1)|1].Min);
        tr[i].Max=max(tr[i<<1].Max,tr[(i<<1)|1].Max);
    }
    int query(int i,int l,int r){  //查询线段树中[l,r] 的最大值 
     
        if(tr[i].l == l && tr[i].r == r)
            return tr[i].Max;
        push_down(i);
        int mid = (tr[i].l + tr[i].r)/2;
        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 findmax(int u,int v){//查询u->v边的最大值
     
        int f1 = top[u], f2 = top[v];
        int tmp = -100000000;
        while(f1 != f2)
        {
            if(deep[f1] < deep[f2])
            {
                swap(f1,f2);
                swap(u,v);
            }
            tmp = max(tmp,query(1,p[f1],p[u]));
            u = fa[f1]; f1 = top[u];
        }
        if(u == v)return tmp;
        if(deep[u] > deep[v]) swap(u,v);
        return max(tmp,query(1,p[son[u]],p[v]));
    }
    void Negate(int u,int v){
        int f1=top[u],f2=top[v];
        while(f1!=f2){
            if(deep[f1]<deep[f2])swap(f1,f2),swap(u,v);
            ne_update(1,p[f1],p[u]);
            u=fa[f1];f1=top[u];
        }
        if(u==v)return;
        if(deep[u]>deep[v])swap(u,v);
        ne_update(1,p[son[u]],p[v]);
        return;
    }
    int E[MAXN][3];
    int main()
    {
        //freopen("Cola.txt","r",stdin);
        freopen("maintaintree.in","r",stdin);
        freopen("maintaintree.out","w",stdout);
        int T,n;
        T=1;
        while(T--){
            init();
            scanf("%d",&n);
            for(int i=0;i<n-1;i++){
                scanf("%d%d%d",&E[i][0],&E[i][1],&E[i][2]);
                addedge(E[i][0],E[i][1]);
                addedge(E[i][1],E[i][0]);
            }
            dfs1(0,1,0);
            dfs2(1,1);
            build(1,0,pos-1);
            for(int i=0;i<n-1;i++){
                if(deep[E[i][0]]>deep[E[i][1]])swap(E[i][0],E[i][1]);
                update(1,p[E[i][1]],E[i][2]);
            }
            char ch[10];
            int u,v;
            while(1){
                scanf("%s",ch);
                if(ch[0]=='D')break;
                scanf("%d%d",&u,&v);
                if(ch[0]=='Q')printf("%d
    ",findmax(u,v));
                else if(ch[0]=='C')update(1,p[E[u-1][1]],v);
                else Negate(u,v);
            }
        }
        return 0;
    }
  • 相关阅读:
    Ethical Hacking
    Ethical Hacking
    Ethical Hacking
    Ethical Hacking
    Ethical Hacking
    Ethical Hacking
    Ethical Hacking
    Can you answer these queries? HDU
    Count the Colors ZOJ
    Balanced Lineup POJ
  • 原文地址:https://www.cnblogs.com/thmyl/p/6883891.html
Copyright © 2020-2023  润新知