• 【BZOJ1036】[ZJOI2008]树的统计Count


    1036: [ZJOI2008]树的统计Count

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

    树链剖分+线段树裸题

    操作1:修改dfs序线段树上某点的值

    操作2:查询dfs序区间和

    操作3:查询dfs序区间max

    贴个板子在这

    /**************************************************************
        Problem: 1036
        User: redwind
        Language: C++
        Result: Accepted
        Time:2268 ms
        Memory:6844 kb
    ****************************************************************/
     
    /*To The End Of The Galaxy*/
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<iomanip>
    #include<stack>
    #include<map>
    #include<set>
    #include<cmath>
    #define debug(x) cerr<<#x<<"="<<x<<endl
    #define INF 0x7f7f7f7f
    #define llINF 0x7fffffffffffll
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    inline int init()
    {
        int now=0,ju=1;char c;bool flag=false;
        while(1)
        {
            c=getchar();
            if(c=='-')ju=-1;
            else if(c>='0'&&c<='9')
            {
                now=now*10+c-'0';
                flag=true;
            }
            else if(flag)return now*ju;
        }
    }
    inline long long llinit()
    {
        long long now=0,ju=1;char c;bool flag=false;
        while(1)
        {
            c=getchar();
            if(c=='-')ju=-1;
            else if(c>='0'&&c<='9')
            {
                now=now*10+c-'0';
                flag=true;
            }
            else if(flag)return now*ju;
        }
    }
    struct segment
    {
        int l,r;
        int sum,max;
    }tree[120004];
    struct edge
    {
        int from,to,val,pre;
    }Edge[60004];
    int dfs_time,cnt=0;
    int size[30005],head[30004],son[30005],top[30005],fa[30005],depth[30005],dfn[30005],rank[30005];
    void predfs(int now,int f,int d)
    {
        depth[now]=d;
        fa[now]=f;
        size[now]++;
        for(int j=head[now];j;j=Edge[j].pre)
        {
            if(Edge[j].to!=f)
            {
                predfs(Edge[j].to,now,d+1);
                size[now]+=size[Edge[j].to];
                if(!son[now]||size[Edge[j].to]>=size[son[now]])
                {
                    son[now]=Edge[j].to;
                }
            }
        }
        return;
    }
    void nextdfs(int now,int tmp)
    {
        top[now]=tmp;
        dfn[now]=++dfs_time;
        rank[dfn[now]]=tmp;
        if(!son[now])return;
        nextdfs(son[now],tmp);
        for(int j=head[now];j;j=Edge[j].pre)
        {
            if(Edge[j].to!=fa[now]&&Edge[j].to!=son[now])
            {
                nextdfs(Edge[j].to,Edge[j].to);
            }
        }
        return ;
    }
    inline void addedge(int from,int to,int val)
    {
        ++cnt;
        Edge[cnt]=((edge){from,to,val,head[from]});
        head[from]=cnt;
    }
    int n;
    #define lson (now<<1)
    #define rson (now<<1|1)
    #define mid ((l+r)>>1)
    void build(int l,int r,int now)
    {
        tree[now].l=l;tree[now].r=r;
        if(l==r)return;
        build(l,mid,lson);
        build(mid+1,r,rson);
    }
    void Modify(int l,int r,int x,int pos,int now)
    {
        tree[now].l=l;tree[now].r=r;
        if(l==r)
        {
            tree[now].sum=tree[now].max=x;
        }
        else
        {
            if(pos<=mid)Modify(l,mid,x,pos,lson);
            else Modify(mid+1,r,x,pos,rson);
            tree[now].max=max(tree[lson].max,tree[rson].max);
            tree[now].sum=tree[lson].sum+tree[rson].sum;
        }
        return;
    }
    int QuerySum(int l,int r,int x,int y,int now)
    {
        if(l==x&&r==y)
        {
            return tree[now].sum;
        }
        else
        {
            if(y<=mid)return QuerySum(l,mid,x,y,lson);
            else if(x>mid)return QuerySum(mid+1,r,x,y,rson);
            else return QuerySum(l,mid,x,mid,lson)+QuerySum(mid+1,r,mid+1,y,rson);
        }
    }
    int QueryMax(int l,int r,int x,int y,int now)
    {
        if(l==x&&r==y)
        {
            return tree[now].max;
        }
        else
        {
            if(y<=mid)return QueryMax(l,mid,x,y,lson);
            else if(x>mid)return QueryMax(mid+1,r,x,y,rson);
            else return max(QueryMax(l,mid,x,mid,lson),QueryMax(mid+1,r,mid+1,y,rson));
        }
    }
    int SolveSum(int x,int y)
    {
        int sum=0;
        while(top[x]!=top[y])
        {
            if(depth[top[x]]<depth[top[y]])swap(x,y);
            sum+=QuerySum(1,n,dfn[top[x]],dfn[x],1);
            x=fa[top[x]];
        }
        if(dfn[x]>dfn[y])swap(x,y);
        sum+=QuerySum(1,n,dfn[x],dfn[y],1);
        return sum;
    }
    int SolveMax(int x,int y)
    {
        int Max=-INF;
        while(top[x]!=top[y])
        {
            if(depth[top[x]]<depth[top[y]])swap(x,y);
            Max=max(Max,QueryMax(1,n,dfn[top[x]],dfn[x],1));
            x=fa[top[x]];
        }
        if(dfn[x]>dfn[y])swap(x,y);
        Max=max(Max,QueryMax(1,n,dfn[x],dfn[y],1));
        return Max;
    }
    int main()
    {
        char type[12];
        int q;
        int a,b;
        n=init();
        for(int i=1;i<n;i++)
        {
            a=init();b=init();
            addedge(a,b,1);
            addedge(b,a,1);
        }
        predfs(1,0,1);
        nextdfs(1,1);
        for(int i=1;i<=n;i++)
        {
            a=init();
            Modify(1,n,a,dfn[i],1);
        }
        q=init();
        for(int i=1;i<=q;i++)
        {
            scanf("%s",type+1);
            if(strcmp(type+1,"QSUM")==0)
            {
                a=init();b=init();
                printf("%d
    ",SolveSum(a,b));
            }
            else if(strcmp(type+1,"QMAX")==0)
            {
                a=init();b=init();
                printf("%d
    ",SolveMax(a,b));
            }
            else
            {
                a=init();b=init();
                Modify(1,n,b,dfn[a],1);
            }
        }
        return 0;
    
    
  • 相关阅读:
    Web 安全 —— XSS攻击的原理
    HTTP缓存
    JavaScript 事件循环机制(Event Loop)
    搭建前端监控系统
    电脑 直接下载cyida deb
    基于样例的传统图像修补算法实现
    Android WorkManager 定时任务
    Android WorkManager工作约束,延迟与查询工作
    微信小程序地图如何显示附近厕所WC步行路线
    物流解决方案再添利器 腾讯位置服务推出货运“三件套”
  • 原文地址:https://www.cnblogs.com/redwind/p/6489831.html
Copyright © 2020-2023  润新知