zoukankan      html  css  js  c++  java
  • 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)

    P2590 [ZJOI2008]树的统计

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

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

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

    (博主)神蒟本蒻,又A了一道树链剖分的模板题,还是太颓废了。。。

    调了我一个小时。。。

    dfs+线段树维护区间和和最大值。

    自带大常常数

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    
    #define LL long long
    #define IL inline
    #define RE register
    #define N 1000000
    using namespace std;
    
    int head[N],tot,n,m,val[N],val_w[N];
    struct node{
        int to,next;
    }e[N];
    
    void add(int u,int v){
        e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
    }
    
    int f[N],siz[N],son[N],top[N],dep[N],id[N],item;
    
    IL void dfs1(int u,int fa){
        f[u]=fa,siz[u]=1,dep[u]=dep[fa]+1;
        int maxson=-1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa) continue;
            dfs1(v,u);
            siz[u]+=siz[v];
            if(siz[v]>maxson) maxson=siz[v],son[u]=v;
        }
    }
    
    IL void dfs2(int u,int topf){
        id[u]=++item,top[u]=topf,val_w[item]=val[u];
        if(!son[u]) return;
        dfs2(son[u],topf);
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==f[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    struct Segment{
        int l,r,w,w_max;
    }tr[N];
    
    IL void push_up(int k){
        tr[k].w_max=max(tr[k<<1].w_max,tr[k<<1|1].w_max);
        tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
    }
    
    IL void build(int k,int l,int r){
        tr[k].l=l,tr[k].r=r;
        if(l==r){tr[k].w=tr[k].w_max=val_w[l];return;}
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        push_up(k);
    }
    
    IL void change(int k,int X,int val_V){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l==r) {tr[k].w_max=tr[k].w=val_V;return;}
        if(X<=mid) change(k<<1,X,val_V);
        else change(k<<1|1,X,val_V);
        push_up(k);
    }
    
    IL int ask_max(int k,int ql,int qr){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=ql&&r<=qr) return tr[k].w_max;
        int ans=-0x7fffffff;
        if(ql<=mid) ans=ask_max(k<<1,ql,qr);
        if(qr>mid) ans=max(ans,ask_max(k<<1|1,ql,qr));
        return ans;
    }
    
    IL int ask_sum(int k,int ql,int qr){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=ql&&r<=qr) return tr[k].w;
        int ans=0;
        if(ql<=mid) ans+=ask_sum(k<<1,ql,qr);
        if(qr>mid) ans+=ask_sum(k<<1|1,ql,qr);
        return ans;
    }
    
    IL int q_max(int u,int v){
        int ans=-0x7fffffff;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            ans=max(ans,ask_max(1,id[top[u]],id[u]));
            u=f[top[u]];
        }
        if(dep[u]<dep[v]) swap(u,v);
        ans=max(ans,ask_max(1,id[v],id[u]));
        return ans;
    }
    
    
    IL int q_sum(int u,int v){
        int ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            ans+=ask_sum(1,id[top[u]],id[u]);
            u=f[top[u]];
        }
        if(dep[u]<dep[v]) swap(u,v);
        ans+=ask_sum(1,id[v],id[u]);
        return ans;
    }
    
    string s;
    
    int main()
    {
        scanf("%d",&n);
        for(int u,v,i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        dfs1(1,1);
        dfs2(1,1);
        build(1,1,n);
        scanf("%d",&m);    
        for(int u,v,i=1;i<=m;i++){
            cin>>s;
            scanf("%d%d",&u,&v);
            if(s=="CHANGE")
                change(1,id[u],v);
            else if(s=="QMAX") printf("%d
    ",q_max(u,v));
            else printf("%d
    ",q_sum(u,v));
        }
        
        return 0;
    }
  • 相关阅读:
    python中list的一种取值方式切片
    python之字典(Dictionary)
    表示数字
    自动收售货系统
    明明的随机数
    自守数
    等差数列
    计算字符个数
    字符统计
    Redraimen的走法
  • 原文地址:https://www.cnblogs.com/song-/p/9777724.html
Copyright © 2011-2022 走看看