zoukankan      html  css  js  c++  java
  • bzoj_1036 树链剖分套线段树

    bzoj_1036

    ★★★★   输入文件:bzoj_1036.in   输出文件:bzoj_1036.out   简单对比
    时间限制:1 s   内存限制:162 MB

    目描述】

    一棵树上有n个节点,编号分别为1n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: 

    I. CHANGE u t : 把结点u的权值改为

    II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 

    III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 

    注意:从点u到点v的路径上的节点包括uv本身

    入格式】

    输入的第一行为一个整数n,表示节点的个数。

    接下来n – 1行,每行2个整数ab,表示节点a和节点b之间有一条边相连。

    接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。

    接下来1行,为一个整数q,表示操作的总数。

    接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 

    对于100%的数据,保证1<=n<=300000<=q<=200000;中途操作中保证每个节点的权值w-3000030000之间。

    出格式】

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

    入】

    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

      

    出】

    4

    1

    2

    2

    10

    6

    5

    6

    5

    16

    #include<bits/stdc++.h>
    #define maxn 30005
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define mid (l+r>>1)
    #define lson ls,l,mid
    #define rson rs,mid+1,r
    using namespace std;
    int n,q;
    vector<int> v[maxn];int a[maxn];
    int size[maxn],son[maxn],fa[maxn],top[maxn],dep[maxn],dfn[maxn],pos[maxn],cnt;
    int sum[maxn<<2],mx[maxn<<2];
    void Dfs(int rt){
        size[rt]=1;
        for(int i=0;i<v[rt].size();i++){
            int to=v[rt][i];
            if(!size[to]){
                fa[to]=rt;
                dep[to]=dep[rt]+1;
                Dfs(to);
                size[rt]+=size[to];
                if(size[to]>size[son[rt]]) son[rt]=to;
            }
        }
    }
    void Dfs(int rt,int tp){
        top[rt]=tp;
        dfn[++cnt]=rt;
        pos[rt]=cnt;
        if(son[rt]) Dfs(son[rt],tp);
        for(int i=0;i<v[rt].size();i++)
            if(!top[v[rt][i]]) Dfs(v[rt][i],v[rt][i]);
    }
    void Build(int rt,int l,int r){
        if(l==r){
            sum[rt]=mx[rt]=a[dfn[l]];
            return;
        }
        Build(lson);Build(rson);
        sum[rt]=sum[ls]+sum[rs];mx[rt]=max(mx[ls],mx[rs]);
    }
    void Add(int rt,int l,int r,int posx,int qx){
        if(l==r){
            sum[rt]=qx;
            mx[rt]=qx;
            return;
        }
        if(posx<=mid) Add(lson,posx,qx);
        else Add(rson,posx,qx);
        sum[rt]=sum[ls]+sum[rs];mx[rt]=max(mx[ls],mx[rs]);
    }
    int Sum(int rt,int l,int r,int s,int t){
        if(s>r||t<l) return 0;
        if(s<=l&&r<=t) return sum[rt];
        return Sum(lson,s,t)+Sum(rson,s,t);
    }
    int Max(int rt,int l,int r,int s,int t){
        if(s>r||t<l) return -maxn;
        if(s<=l&&r<=t) return mx[rt];
        return max(Max(lson,s,t),Max(rson,s,t));
    }
    int lca(int x,int y,bool opt){
        int res;
        if(opt) res=0;
        else res=-maxn;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            if(opt) res+=Sum(1,1,n,pos[top[x]],pos[x]);
            else res=max(res,Max(1,1,n,pos[top[x]],pos[x]));
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        if(opt) res+=Sum(1,1,n,pos[x],pos[y]);
            else res=max(res,Max(1,1,n,pos[x],pos[y]));
        return res;
    }
    int main()
    {
        freopen("bzoj_1036.in","r",stdin);
        freopen("bzoj_1036.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int x,y;scanf("%d%d",&x,&y);
            v[x].push_back(y);v[y].push_back(x);
        }    
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        Dfs(1);Dfs(1,1);Build(1,1,n);
        scanf("%d",&q);
        while(q--){
            string s;cin>>s;
            if(s[0]=='C'){
                int x,v;
                scanf("%d%d",&x,&v);
                Add(1,1,n,pos[x],v);
            }
            if(s[1]=='M'){
                int x,y;scanf("%d%d",&x,&y);
                printf("%d
    ",lca(x,y,0));
            }
            if(s[1]=='S'){
                int x,y;scanf("%d%d",&x,&y);
                printf("%d
    ",lca(x,y,1));
            }
        }
        return 0;
    }

    唉 编程不易啊

    考试的时候就写错了两行就爆0了!!!!

    那个dfn数组  和  pos数组

    在从外面进入线段树的时候要用pos

    从线段树里调用外面的时候要用dfn

    千万要记住!!

    还有一个地方  就是那个Max函数  如果越界 返回值一定要是一个负无穷   否则万一本来最大值就是一个负数  而你越界了反而返回了一个0 那不就出bug了吗    还是要灵活变通啊!

    加油 多练练就好了

    ヾ(◍°∇°◍)ノ゙

  • 相关阅读:
    vscode安装设置go
    Go开发环境搭建
    使用Docker镜像
    Docker for mac安装
    封装request.get_params批量取值
    Python之日志处理(logging模块)
    Python3 urllib.parse 常用函数示例
    前端之CSS属性相关
    前端之CSS选择器
    前端之CSS介绍
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11325407.html
Copyright © 2011-2022 走看看