• Evanyou Blog 彩带


      题目传送门

    树的统计

    题目描述

    一棵树上有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之间。


      分析:

      一开始看到以为是个什么很难的数据结构,然后仔细看了一边题面,这不就是个树剖裸题吗?

      用结构体写会方便很多,而且因为只有单点修改,所以连下放标记都不需要。我一开始写了个SB特判卡了半天。。。。。。

      Code:

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=0x7f7f7f7f;
    const int N=3e4+7;
    int n,m,a[N],head[N],cnt,id,dfn[N],nu[N];
    int hson[N],fa[N],dep[N],top[N],size[N];
    struct Node{int to,next;}edge[N<<1];
    struct Seg{
        int tot;int mx;
        friend Seg operator + (const Seg a,const Seg b)
        {
            Seg ret;
            ret.tot=a.tot+b.tot;
            ret.mx=max(a.mx,b.mx);
            return ret;
        }
    }t[N<<8];
    inline int read()
    {
        char ch=getchar();int num=0;bool flag=false;
        while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
        while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
        return flag?-num:num;
    }
    inline void add(int x,int y)
    {
        edge[++cnt].to=y;
        edge[cnt].next=head[x];
        head[x]=cnt;
    }
    inline void dfs1(int u)
    {
        size[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==fa[u])continue;
            fa[v]=u;dep[v]=dep[u]+1;
            dfs1(v);size[u]+=size[v];
            if(size[v]>size[hson[u]])
            hson[u]=v;}
    }
    inline void dfs2(int u,int now)
    {
        dfn[++id]=u;nu[u]=id;top[u]=now;
        if(!hson[u])return;dfs2(hson[u],now);
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==fa[u]||v==hson[u])continue;
            dfs2(v,v);}
    }
    inline void pushup(int rt)
    {
        t[rt]=t[rt<<1]+t[rt<<1|1];
    }
    inline void build(int l,int r,int rt)
    {
        if(l>r)return;
        if(l==r){
        t[rt].tot=t[rt].mx=a[dfn[l]];
        return;}
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    } 
    inline void update(int l,int r,int rt,int L,int R,int C)
    {
        if(l>R||r<L)return;
        if(l==L&&r==R){
        t[rt].tot=t[rt].mx=C;
        return;}
        int mid=(l+r)>>1;
        update(l,mid,rt<<1,L,R,C);
        update(mid+1,r,rt<<1|1,L,R,C);
        pushup(rt);
    }
    inline Seg quary(int l,int r,int rt,int L,int R)
    {
        Seg ret;ret.tot=0;ret.mx=-inf;
        if(l>R||r<L)return ret;
        if(L<=l&&r<=R)return t[rt];
        int mid=(l+r)>>1;
        if(L<=mid)ret=ret+quary(l,mid,rt<<1,L,R);
        if(R>mid)ret=ret+quary(mid+1,r,rt<<1|1,L,R);
        return ret;
    }
    inline Seg get(int x,int y)
    {
        int fax=top[x],fay=top[y];
        Seg ans;ans.tot=0;ans.mx=-inf;
        while(fax!=fay){
            if(dep[fax]<dep[fay])swap(x,y),swap(fax,fay);
            ans=ans+quary(1,n,1,nu[fax],nu[x]);
            x=fa[fax];fax=top[x];}
        if(x!=y){
            if(dep[x]>dep[y])swap(x,y);}
        ans=ans+quary(1,n,1,nu[x],nu[y]);
        return ans;
    }
    int main()
    {
        n=read();int x,y;
        memset(head,-1,sizeof(head));
        for(int i=1;i<n;i++){
        x=read();y=read();
        add(x,y);add(y,x);}
        for(int i=1;i<=n;i++)
        a[i]=read();
        fa[1]=0;dep[1]=1;
        dfs1(1);dfs2(1,1);
        build(1,n,1);m=read();
        for(int i=1;i<=m;i++){
            char opt[10];
            scanf("%s",opt);
            x=read();y=read();
            if(opt[0]=='C')
            update(1,n,1,nu[x],nu[x],y);
            else {Seg ans=get(x,y);
            if(opt[1]=='M')printf("%d
    ",ans.mx);
            else printf("%d
    ",ans.tot);}}
        return 0;
    }
  • 相关阅读:
    20199319 2019-2020-2 《网络攻防实践》第七周作业
    《访问控制策略描述和应用》阅读总结
    密码学基础学习-序列密码
    密码学基础学习-1
    《一种普适计算下的访问控制策略》阅读总结
    20199319 2019-2020-2 《网络攻防实践》第五周作业
    《访问控制策略描述语言与策略冲突研究》阅读总结
    20199319 2019-2020-2 《网络攻防实践》第四周作业
    20199319 2019-2020-2 《网络攻防实践》第三周作业
    记录旧手机(米6)安装Linux(Ubuntu16.04)踩过的坑
  • 原文地址:https://www.cnblogs.com/cytus/p/9132797.html
Copyright © 2020-2023  润新知