zoukankan      html  css  js  c++  java
  • 洛谷 P2590 [ZJOI2008]树的统计

    题目描述

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

    我们将以下面的形式来要求你对这棵树完成一些操作:

    I. CHANGE u t : 把结点u的权值改为t

    II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

    III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

    注意:从点u到点v的路径上的节点包括u和v本身

    输入输出格式

    输入格式:

    输入文件的第一行为一个整数n,表示节点的个数。

    接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

    接下来一行n个整数,第i个整数wi表示节点i的权值。

    接下来1行,为一个整数q,表示操作的总数。

    接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

    输出格式:

    对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    输入输出样例

    输入样例#1:
    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4
    
    输出样例#1:
    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    

    说明

    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    模版树剖 

    屠龙宝刀点击就送

    #include <ctype.h>
    #include <cstdio>
    #define N 50000
    
    void read(int &x)
    {
        x=0;
        bool f=0;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        x=f?(~x)+1:x;
    }
    struct Edge
    {
        int next,to;
    }edge[N<<1];
    
    struct Tree
    {
        int l,r,dis,Max;
        Tree *left,*right;
        Tree()
        {
            left=right=NULL;
            dis=Max=0;
        }
    }*root;
    int dfn[N],Q,dis[N],head[N],cnt,n,top[N],fa[N],dep[N],tim,size[N],belong[N];
    int max(int a,int b) {return a>b?a:b;} 
    void add(int u,int v)
    {
        ++cnt;
        edge[cnt].next=head[u];
        edge[cnt].to=v;
        head[u]=cnt;
    }
    void dfs1(int x)
    {
        size[x]=1;
        dep[x]=dep[fa[x]]+1;
        for(int i=head[x];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(fa[x]!=v)
            {
                fa[v]=x;
                dfs1(v);
                size[x]+=size[v];
            }
        }
    }
    void dfs2(int x)
    {
        belong[x]=++tim;
        dfn[tim]=x;
        int t=0;
        if(!top[x]) top[x]=x;
        for(int i=head[x];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(fa[x]!=v&&size[t]<size[v]) t=v;
        }
        if(t) top[t]=top[x],dfs2(t);
        for(int i=head[x];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(fa[x]!=v&&v!=t) dfs2(v);
        }
    }
    void build(Tree *&k,int l,int r)
    {
        k=new Tree;
        k->l=l;k->r=r;
        if(l==r)
        {
            k->dis=k->Max=dis[dfn[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(k->left,l,mid);
        build(k->right,mid+1,r);
        k->dis=k->left->dis+k->right->dis;
        k->Max=max(k->left->Max,k->right->Max);
    }
    void Tree_change(Tree *&k,int t,int z)
    {
        if(k->l==k->r)
        {
            k->dis=k->Max=z;
            return;
        }
        int mid=(k->l+k->r)>>1;
        if(mid>=t) Tree_change(k->left,t,z);
        else Tree_change(k->right,t,z);
        k->dis=k->left->dis+k->right->dis;
        k->Max=max(k->left->Max,k->right->Max);
    }
    void swap(int &x,int &y)
    {
        int tmp=y;
        y=x;
        x=tmp;
    }
    int Tree_Query_Max(Tree *&k,int l,int r)
    {
        if(k->l==l&&k->r==r) return k->Max;
        int mid=(k->l+k->r)>>1;
        if(l>mid) return Tree_Query_Max(k->right,l,r);
        else if(r<=mid) return Tree_Query_Max(k->left,l,r);
        else return max(Tree_Query_Max(k->left,l,mid),Tree_Query_Max(k->right,mid+1,r));
    }
    int Chain_Query_Max(int x,int y)
    {
        int ans=-0x7fffffff;
        for(;top[x]!=top[y];x=fa[top[x]])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans=max(ans,Tree_Query_Max(root,belong[top[x]],belong[x]));
        }
        if(belong[x]>belong[y]) swap(x,y);
        ans=max(ans,Tree_Query_Max(root,belong[x],belong[y]));
        return ans;
    }
    int Tree_Query_Sum(Tree *&k,int l,int r)
    {
        if(k->l==l&&k->r==r) return k->dis;
        int mid=(k->l+k->r)>>1;
        if(l>mid) return Tree_Query_Sum(k->right,l,r);
        else if(r<=mid) return Tree_Query_Sum(k->left,l,r);
        else return Tree_Query_Sum(k->left,l,mid)+Tree_Query_Sum(k->right,mid+1,r);
    }
    int Chain_Query_Sum(int x,int y)
    {
        int ans=0;
        for(;top[x]!=top[y];x=fa[top[x]])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans+=Tree_Query_Sum(root,belong[top[x]],belong[x]);
        }
        if(belong[x]>belong[y]) swap(x,y);
        ans+=Tree_Query_Sum(root,belong[x],belong[y]);
        return ans;
    }
    int main()
    {
        read(n);
        for(int a,b,i=1;i<n;i++)
        {
            read(a);
            read(b);
            add(a,b);
            add(b,a);
        }
        for(int i=1;i<=n;i++) read(dis[i]);
        dfs1(1);
        dfs2(1);
        read(Q);
        root=new Tree;
        build(root,1,n);
        char str[11];
        for(int x,y;Q--;)
        {
            scanf("%s",str+1);
            if(str[1]=='C')
            {
                read(x);
                read(y);
                Tree_change(root,belong[x],y);
            }
            else if(str[2]=='M')
            {
                read(x);
                read(y);
                printf("%d
    ",Chain_Query_Max(x,y));
            }
            else
            {
                read(x);
                read(y);
                printf("%d
    ",Chain_Query_Sum(x,y));
            }
        }
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    操作系统复习
    Google hack语法
    c++的set重载运算符
    华为笔试题
    Flume+Kafka整合
    kafka相关知识点总结
    kafka中生产者和消费者API
    Kafka集群环境搭建
    Storm消息容错机制(ack-fail机制)
    Storm通信机制(了解)
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7196954.html
Copyright © 2011-2022 走看看