• BZOJ1036: [ZJOI2008]树的统计Count


    Description

      一棵树上有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本身

    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 <bits/stdc++.h>
    #define ull unsigned long long
    using namespace std;
    const int N=1e5+100;
    int n,m,tot,cnt;
    int fa[N],last[N];
    int son[N],deep[N],dfn[N],num[N],top[N];//重儿子 深度 dfs序 子树规模 所在重链的顶端节点
    int sum[N*4],mx[N*4],w[N];
    struct orz{
        int v,nex;}e[N];
    char op[10];
    void init()
    {
        cnt=0;
        tot=0;
        memset(last,0,sizeof(last));
        memset(son,-1,sizeof(son));
    }
    void Insert(int x,int y)
    {
        cnt++;
        e[cnt].v=y;
        e[cnt].nex=last[x];
        last[x]=cnt;
    }
    void dfs1(int x,int d,int pre)
    {
        fa[x]=pre;
        deep[x]=d;
        num[x]=1;
        for (int i=last[x];i;i=e[i].nex)
        {
            int v=e[i].v;
            if (v==fa[x]) continue;
            dfs1(v,d+1,x);
            num[x]+=num[v];
            if (son[x]==-1 || num[v]>num[son[x]]) son[x]=v;
        }
    }
    void dfs2(int x,int sp)
    {
        top[x]=sp;
        dfn[x]=++tot;
        if (son[x]==-1) return ;
        dfs2(son[x],sp);
        for (int i=last[x];i;i=e[i].nex)
        {
            int v=e[i].v;
            if (v==fa[x]) continue;
            if (v!=son[x]) dfs2(v,v);
        }
    }
    void PushUp(int s)
    {
        sum[s]=sum[s<<1]+sum[s<<1|1];
        mx[s]=max(mx[s<<1],mx[s<<1|1]);
    }
    void build(int s,int l,int r)
    {
        mx[s]=sum[s]=0;
        if (l==r) return ;
        int m=(l+r)>>1;
        build(s<<1,l,m); build(s<<1|1,m+1,r);
        PushUp(s);
    }
    void update(int s,int l,int r,int pos,int val)
    {
        if (l==r)
        {
            mx[s]=sum[s]=val;
            return ;
        }
        int mid=(l+r)>>1;
        if (pos<=mid) update(s<<1,l,mid,pos,val);
        else update(s<<1|1,mid+1,r,pos,val);
        PushUp(s);
    }
    int querymx(int s,int l,int r,int L,int R)
    {
        //printf("s=%d,l=%d,r=%d,L=%d,R=%d
    ",s,l,r,L,R);
        if (L<=l&&r<=R) return mx[s];
        int mid=(l+r)>>1;
        int ans=INT_MIN;
        if (L<=mid) ans=max(ans,querymx(s<<1,l,mid,L,R));
        if (R>mid) ans=max(ans,querymx(s<<1|1,mid+1,r,L,R));
        return ans;
    }
    int querysum(int s,int l,int r,int L,int R)
    {
        if (L<=l&&r<=R) return sum[s];
        int mid=(l+r)>>1;
        int ans=0;
        if (L<=mid) ans+=querysum(s<<1,l,mid,L,R);
        if (R>mid) ans+=querysum(s<<1|1,mid+1,r,L,R);
        return ans;
    }
    void solve(int op,int x, int y)
    {
        if (op==1)
        {
            int mx=INT_MIN;
            while (top[x]!=top[y])
            {
                if (deep[top[x]]<deep[top[y]]) swap(x, y);
                mx=max(mx,querymx(1,1,n,dfn[top[x]],dfn[x]));
                x=fa[top[x]];
            }
            if (deep[x]>deep[y]) swap(x,y);
            mx=max(mx,querymx(1,1,n,dfn[x],dfn[y]));
            printf("%d
    ",mx);
        }
        else
        {
            int ans=0;
            while (top[x]!=top[y])
            {
                if (deep[top[x]]<deep[top[y]]) swap(x, y);
                ans+=querysum(1,1,n,dfn[top[x]],dfn[x]);
                x=fa[top[x]];
            }
            if (deep[x]>deep[y]) swap(x,y);
            ans+=querysum(1,1,n,dfn[x],dfn[y]);
            printf("%d
    ",ans);
        }
    }
    
    int main()
    {
        while (scanf("%d",&n)!=EOF)
        {
            init();
            int u,v;
            for (int i=1;i<n;i++)
            {
                scanf("%d%d",&u,&v);
                Insert(u,v);
                Insert(v,u);
            }
            dfs1(1,0,0); //cout<<'*'<<endl;
            dfs2(1,1);
    
            build(1,1,n);
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&u);
                update(1,1,n,dfn[i],u);
            }
            scanf("%d",&m);
    
            while (m--)
            {
                scanf("%s",op);
                if (op[0]=='C')
                {
                    scanf("%d%d",&u,&v);
                    update(1,1,n,dfn[u],v);
                }
                else
                {
                    scanf("%d%d",&u,&v);
                    if (op[1]=='M') solve(1,u,v);
                    else solve(2,u,v);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    QtQt Creator 操作快捷键大全
    go编译报错https://proxy.golang.org/github.com/ i/o timeout
    常用坐标系
    10 种CORS跨域解决方案
    centos问题解决方案汇总
    org.apache.axis.AxisFault: 服务器无法处理请求。 > 值不能为空。
    PHP 开启 curl_init
    帝国CMS 标签 showclasstemp
    帝国CMS 标签 listsonclass
    PHP 获取服务器 MAC 物理网卡地址
  • 原文地址:https://www.cnblogs.com/tetew/p/11293927.html
Copyright © 2020-2023  润新知