• 洛谷 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之间。

    题解:我懒得写一棵线段树两种操作了,所以索性写了两棵线段树,一棵 清蒸  求区间最大值,一棵红烧 求区间和

    单点修改的时候,就同时修改两棵树。查询就是最经典的路径查询啦~

    代码写了4k,还暗自窃喜自己终于写了一长度4k的代码,回去一看,什么鬼,我树剖模板题都写的比这个长?

    也是醉了,代码如下:

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lson root<<1
    #define rson root<<1|1
    using namespace std;
    
    struct node
    {
        int m,l,r;
    } tr_sum[120120],tr_max[120120];
    int size[30030],deep[30030],fa[30030],son[30030],id[30030],top[30030],w[30030],c[30030],cnt;
    vector<int> g[30030];
    
    void push_up_sum(int root)
    {
        tr_sum[root].m=tr_sum[lson].m+tr_sum[rson].m;
    }
    
    void push_up_max(int root)
    {
        tr_max[root].m=max(tr_max[lson].m,tr_max[rson].m);
    }
    
    void build_sum(int root,int l,int r)
    {
        if(l==r)
        {
            tr_sum[root].l=l;
            tr_sum[root].r=r;
            tr_sum[root].m=w[l];
            return ;
        }
        tr_sum[root].l=l;
        tr_sum[root].r=r;
        int mid=(l+r)>>1;
        build_sum(lson,l,mid);
        build_sum(rson,mid+1,r);
        push_up_sum(root);
    }
    
    void build_max(int root,int l,int r)
    {
        if(l==r)
        {
            tr_max[root].l=l;
            tr_max[root].r=r;
            tr_max[root].m=w[l];
            return ;
        }
        tr_max[root].l=l;
        tr_max[root].r=r;
        int mid=(l+r)>>1;
        build_max(lson,l,mid);
        build_max(rson,mid+1,r);
        push_up_max(root);
    }
    
    void update(int root,int x,int val)
    {
        if(x==tr_sum[root].l&&x==tr_sum[root].r)
        {
            tr_sum[root].m=val;
            tr_max[root].m=val;
            return ;
        }
        int mid=(tr_sum[root].l+tr_sum[root].r)>>1;
        if(x>mid)
        {
            update(rson,x,val);
        }
        else
        {
            update(lson,x,val);
        }
        push_up_sum(root);
        push_up_max(root);
    }
    
    int query_sum(int root,int l,int r)
    {
        if(l==tr_sum[root].l&&r==tr_sum[root].r)
        {
            return tr_sum[root].m;
        }
        int mid=(tr_sum[root].l+tr_sum[root].r)>>1;
        if(l>mid)
        {
            return query_sum(rson,l,r);
        }
        else
        {
            if(r<=mid)
            {
                return query_sum(lson,l,r);
            }
            else
            {
                return query_sum(lson,l,mid)+query_sum(rson,mid+1,r);
            }
        }
    }
    
    int query_max(int root,int l,int r)
    {
        if(l==tr_max[root].l&&r==tr_max[root].r)
        {
            return tr_max[root].m;
        }
        int mid=(tr_max[root].l+tr_max[root].r)>>1;
        if(l>mid)
        {
            return query_max(rson,l,r);
        }
        else
        {
            if(r<=mid)
            {
                return query_max(lson,l,r);
            }
            else
            {
                return max(query_max(lson,l,mid),query_max(rson,mid+1,r));
            }
        }
    }
    
    void dfs1(int now,int f,int dep)
    {
        fa[now]=f;
        deep[now]=dep;
        size[now]=1;
        int maxson=-1;
        for(int i=0; i<g[now].size(); i++)
        {
            if(g[now][i]==f)
            {
                continue;
            }
            dfs1(g[now][i],now,dep+1);
            size[now]+=size[g[now][i]];
            if(size[g[now][i]]>maxson)
            {
                son[now]=g[now][i];
                maxson=size[g[now][i]];
            }
        }
    }
    
    void dfs2(int now,int topf)
    {
        id[now]=++cnt;
        w[cnt]=c[now];
        top[now]=topf;
        if(!son[now])
        {
            return ;
        }
        dfs2(son[now],topf);
        for(int i=0; i<g[now].size(); i++)
        {
            if(g[now][i]==fa[now]||g[now][i]==son[now])
            {
                continue;
            }
            dfs2(g[now][i],g[now][i]);
        }
    }
    
    int path_query_max(int x,int y)
    {
        int ans=-100000;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])
            {
                swap(x,y);
            }
            ans=max(ans,query_max(1,id[top[x]],id[x]));
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])
        {
            swap(x,y);
        }
        ans=max(ans,query_max(1,id[x],id[y]));
        return ans;
    }
    
    int path_query_sum(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])
            {
                swap(x,y);
            }
            ans+=query_sum(1,id[top[x]],id[x]);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])
        {
            swap(x,y);
        }
        ans+=query_sum(1,id[x],id[y]);
        return ans;
    }
    
    int main()
    {
        int n,m;
        scanf("%d",&n);
        for(int i=1; i<=n-1; i++)
        {
            int from,to;
            scanf("%d%d",&from,&to);
            g[from].push_back(to);
            g[to].push_back(from);
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&c[i]);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        build_sum(1,1,n);
        build_max(1,1,n);
        scanf("%d",&m);
        char s[10];
        int u,v;
        for(int i=1; i<=m; i++)
        {
            scanf("
    %s %d %d",s,&u,&v);
            if(s[0]=='C')
            {
                update(1,id[u],v);
            }
            if(s[0]=='Q')
            {
                if(s[1]=='S')
                {
                    printf("%d
    ",path_query_sum(u,v));
                }
                if(s[1]=='M')
                {
                    printf("%d
    ",path_query_max(u,v));
                }
            }
        }
    }
  • 相关阅读:
    poi隐藏列
    凯西太太的果园
    java中不可变对象深入理解
    excel添加空白行的快捷键
    如何在多个页面中,引入一个公共组件
    对后端返回的数据进行适配
    我与时间管理的故事
    在前端团队的那些日子(初见)
    我是这样做时间管理的(下)
    我是这样做时间管理的(上)
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/8676262.html
Copyright © 2020-2023  润新知