• bzoj1036:


    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 18717  Solved: 7640
    [Submit][Status][Discuss]

    Description

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

      输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
    一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
    的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

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

    Sample Input

    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

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    题解
    树链剖分模板题
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define maxn 30005
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    #define inf 1<<29
    using namespace std;
    int data[maxn],n,sum[maxn<<2],maxx[maxn<<2],tree[maxn],siz[maxn],head[maxn],deep[maxn],son[maxn],pre[maxn];
    int ecnt,fa[maxn],ord,top[maxn];
    struct edge{
        int u,v,next;
    }E[maxn*2];
    void add(int u,int v)
    {
        E[++ecnt].u=u;
        E[ecnt].v=v;
        E[ecnt].next=head[u];
        head[u]=ecnt;
    }
    void pushup(int o)
    {
        sum[o]=sum[o<<1]+sum[o<<1|1];
        maxx[o]=max(maxx[o<<1],maxx[o<<1|1]);
    }
    void dfs(int num)
    {
        siz[num]=1;
        for(int i=head[num] ; i ; i=E[i].next )
        {
            int v=E[i].v;
            if(fa[num]==v)continue;
            fa[v]=num;
            deep[v]=deep[num]+1;
            dfs(v);
            siz[num]+=siz[v];
            if(siz[son[num]]<siz[v])son[num]=v;
        }
    }
    void dfs2(int num,int tp)
    {
        tree[num]=++ord;top[num]=tp;pre[tree[num]]=num;
        if(son[num])dfs2(son[num],tp);
        for(int i=head[num] ; i ; i=E[i].next )
        {
            int v=E[i].v;
            if(son[num]==v||fa[num]==v)continue;
            dfs2(v,v);
        }
    }
    void build(int o,int l,int r)
    {
        if(l==r)
        {
            sum[o]=maxx[o]=data[pre[l]];
            return ;
        }
        int m=(l+r)>>1;
        build(lson);build(rson);
        pushup(o);
        return ;
    }
    void update(int o,int l,int r,int x,int val)
    {
        if(l==r)
        {
            sum[o]=val;
            maxx[o]=val;
            return ;
        }
        int m=(l+r)>>1;
        if(x<=m)update(lson,x,val);
        else update(rson,x,val);
        pushup(o);
        return ;
    }
    int query_max(int o,int l,int r,int ql,int qr)
    {
        if(ql<=l&&r<=qr)
        {
            return maxx[o];
        }
        int ret=-inf;
        int m=(l+r)>>1;
        if(ql<=m)ret=max(ret,query_max(lson,ql,qr));
        if(qr>m)ret=max(ret,query_max(rson,ql,qr));
        return ret;
    }
    int que_max(int x,int y)
    {
        int fx=top[x],fy=top[y];
        int ans=-inf;
        while(fx!=fy)
        {
            if(deep[fx]<deep[fy]){swap(fx,fy);swap(x,y);}
            ans=max(ans,query_max(1,1,n,tree[fx],tree[x]));
            x=fa[fx];fx=top[x];
        }
        if(deep[x]>deep[y]){swap(x,y);}
        ans=max(ans,query_max(1,1,n,tree[x],tree[y]));
        return ans;
    }
    int query_sum(int o,int l,int r,int ql,int qr)
    {
        if(ql<=l&&r<=qr)
        {
            return sum[o];
        }
        int ret(0);
        int m=(l+r)>>1;
        if(ql<=m)ret+=query_sum(lson,ql,qr);
        if(qr>m)ret+=query_sum(rson,ql,qr);
        return ret;
    }
    int que_sum(int x,int y)
    {
        int ret(0);
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(deep[fx]<deep[fy])
            {
                swap(fx,fy);swap(x,y);
            }
            ret+=query_sum(1,1,n,tree[fx],tree[x]);
            x=fa[fx];fx=top[x];
        }
        if(deep[y]<deep[x])swap(x,y);
        ret+=query_sum(1,1,n,tree[x],tree[y]);
        return ret;
    }
    int main()
    {
        int a,b,q;
        char str[10];
        scanf("%d",&n);
        for(int i=1 ; i<n ; ++i )
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(int i=1 ; i<=n ; ++i )
        {
            scanf("%d",&data[i]);
        }
        dfs(1);dfs2(1,1);build(1,1,n);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%s",str);
            scanf("%d%d",&a,&b);
            if(str[0]=='C')
            {
                update(1,1,n,tree[a],b);
                data[a]=b;
            }
            if(str[1]=='M')
            {
                printf("%d
    ",que_max(a,b));
            }
            if(str[1]=='S')
            {
                printf("%d
    ",que_sum(a,b));
            }
        }
        return 0;
    }
  • 相关阅读:
    Flink sql 写 Hbase 忽略空列
    python协程系列(一)——生成器generator以及yield表达式详解
    Python中可迭代对象,迭代器和生成器的异同点
    Python生成器: send函数、close函数与yield关键字协作
    sqlalchemy的基本用法
    Windows10激活后又提示未激活解决办法
    parseaddr函数和formataddr函数的用法
    VisualStudio Code Remote 调试方法(错误Containers Docker version 17.12.0 or later required.)
    SpringBoot Jar Windows CMD 运行卡顿
    使用Aspose.cells(java)将excel转为图片等
  • 原文地址:https://www.cnblogs.com/fujudge/p/7610626.html
Copyright © 2020-2023  润新知