zoukankan      html  css  js  c++  java
  • AC日记——[ZJOI2008]树的统计Count bzoj 1036

    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 15007  Solved: 6092
    [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

    HINT

     

    Source

    思路:

      裸线段树。

    来,上代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    
    #define maxn 30001
    
    using namespace std;
    
    struct TreeNodeType {
        int l,r,dis,mid,max_;
    };
    struct TreeNodeType tree[maxn<<2];
    
    struct EdgeType {
        int to,next;
    };
    struct EdgeType edge[maxn<<1];
    
    int if_z,n,m,dis[maxn],Enum,f[maxn],deep[maxn];
    int size[maxn],tot,flag[maxn],belong[maxn],dis_[maxn];
    int head[maxn],cnt;
    
    char Cget;
    
    inline void read_int(int &now)
    {
        if_z=1,now=0,Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
        now*=if_z;
    }
    
    inline void edge_add(int from,int to)
    {
        edge[++Enum].to=from,edge[Enum].next=head[to],head[to]=Enum;
        edge[++Enum].to=to,edge[Enum].next=head[from],head[from]=Enum;
    }
    
    void search(int now,int fa)
    {
        int pos=tot++;
        f[now]=fa,deep[now]=deep[fa]+1;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].to==fa) continue;
            search(edge[i].to,now);
        }
        size[now]=tot-pos;
    }
    
    void search_(int now,int chain)
    {
        flag[now]=++cnt,belong[now]=chain;
        dis_[flag[now]]=dis[now];
        int pos=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(flag[edge[i].to]) continue;
            if(size[edge[i].to]>size[pos]) pos=edge[i].to;
        }
        if(pos!=0) search_(pos,chain);
        else return ;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(flag[edge[i].to]) continue;
            search_(edge[i].to,edge[i].to);
        }
    }
    
    int max(int SOME1,int SOME2)
    {
        if(SOME1>SOME2) return SOME1;
        else return SOME2;
    }
    
    inline void tree_up(int now)
    {
        tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis;
        tree[now].max_=max(tree[now<<1].max_,tree[now<<1|1].max_);
    }
    
    void tree_build(int now,int l,int r)
    {
        tree[now].l=l,tree[now].r=r;
        if(l==r)
        {
            tree[now].dis=dis_[++cnt];
            tree[now].max_=dis_[cnt];
            return ;
        }
        tree[now].mid=(l+r)>>1;
        tree_build(now<<1,l,tree[now].mid);
        tree_build(now<<1|1,tree[now].mid+1,r);
        tree_up(now);
    }
    
    void tree_change(int now,int to,int x)
    {
        if(tree[now].l==tree[now].r&&tree[now].l==to)
        {
            tree[now].dis=x,tree[now].max_=x;
            return ;
        }
        if(to>tree[now].mid) tree_change(now<<1|1,to,x);
        else tree_change(now<<1,to,x);
        tree_up(now);
    }
    
    int tree_query_max(int now,int l,int r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            return tree[now].max_;
        }
        if(l>tree[now].mid) return tree_query_max(now<<1|1,l,r);
        else if(r<=tree[now].mid) return tree_query_max(now<<1,l,r);
        else return max(tree_query_max(now<<1,l,tree[now].mid),tree_query_max(now<<1|1,tree[now].mid+1,r));
    }
    
    int tree_query_dis(int now,int l,int r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            return tree[now].dis;
        }
        if(l>tree[now].mid) return tree_query_dis(now<<1|1,l,r);
        else if(r<=tree[now].mid) return tree_query_dis(now<<1,l,r);
        else return tree_query_dis(now<<1,l,tree[now].mid)+tree_query_dis(now<<1|1,tree[now].mid+1,r);
    }
    
    inline int solve_dis(int x,int y)
    {
        int ans=0;
        while(belong[x]!=belong[y])
        {
            if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
            ans+=tree_query_dis(1,flag[belong[x]],flag[x]);
            x=f[belong[x]];
        }
        ans+=tree_query_dis(1,min(flag[x],flag[y]),max(flag[x],flag[y]));
        return ans;
    }
    
    inline int solve_max(int x,int y)
    {
        int ans=-0x7ffffff;
        while(belong[x]!=belong[y])
        {
            if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
            ans=max(ans,tree_query_max(1,flag[belong[x]],flag[x]));
            x=f[belong[x]];
        }
        ans=max(ans,tree_query_max(1,min(flag[x],flag[y]),max(flag[x],flag[y])));
        return ans;
    }
    
    int main()
    {
        read_int(n);
        int from,to;
        for(int i=1;i<n;i++)
        {
            read_int(from),read_int(to);
            edge_add(from,to);
        }
        for(int i=1;i<=n;i++) read_int(dis[i]);
        search(1,0),search_(1,1),cnt=0,tree_build(1,1,n);
        read_int(m);
        char ch[10];
        for(int i=1;i<=m;i++)
        {
            scanf("%s",ch);read_int(from),read_int(to);
            if(ch[0]=='C')
            {
                tree_change(1,flag[from],to);
            }
            else
            {
                if(ch[1]=='S') printf("%d
    ",solve_dis(from,to));
                else printf("%d
    ",solve_max(from,to));
            }
        }
        return 0;
    }
  • 相关阅读:
    Android WebView使用
    Android
    Instant Buy Android API Tutorial
    cocos2dx 手势识别
    cocos2d-x 判断两条直线是否相交
    golang 环境bash 以及shell
    技术描述
    golang web开发获取get、post、cookie参数
    Linux curl 模拟form表单提交信息和文件
    Golang HTTP文件上传
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6362796.html
Copyright © 2011-2022 走看看