zoukankan      html  css  js  c++  java
  • LUOGU P2590 [ZJOI2008]树的统计

    传送门

    解题思路

    树链剖分,把dfs序用线段树维护,记录一个最大值,记录一个和,两个函数。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    
    using namespace std;
    const int MAXN=30005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n,m,num,cnt,head[MAXN],to[MAXN<<1],nxt[MAXN<<1],a[MAXN];
    int sum[MAXN<<2],lazy[MAXN<<2],fa[MAXN],siz[MAXN],son[MAXN],dep[MAXN];
    int id[MAXN],top[MAXN],Max[MAXN<<2],w[MAXN];
    
    inline void add(int bg,int ed){
        to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
    }
    
    void dfs1(int x,int f,int d){
        dep[x]=d,fa[x]=f,siz[x]=1;
        int maxson=-1;
        for(register int i=head[x];i;i=nxt[i]){
            int u=to[i];if(u==f) continue;
            dfs1(u,x,d+1);
            siz[x]+=siz[u];
            if(siz[u]>maxson) {maxson=siz[u];son[x]=u;}
        }
    }
    
    void dfs2(int x,int topf){
        top[x]=topf,id[x]=++num,w[num]=a[x];
        if(!son[x]) return;
        dfs2(son[x],topf);
        for(register int i=head[x];i;i=nxt[i]){
            int u=to[i];if(u==son[x] || u==fa[x]) continue;
            dfs2(u,u);
        }
    }
    
    //--------------------xds----------------------
    
    inline void pushup(int x){
        sum[x]=sum[x<<1]+sum[x<<1|1];
        Max[x]=max(Max[x<<1],Max[x<<1|1]);
    }
    
    void build(int x,int l,int r){
        if(l==r){
            sum[x]=w[l];
            Max[x]=w[l];
            return;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    
    void update(int x,int l,int r,int L,int R,int k){
        if(L<=l && r<=R){
            sum[x]=k;
            Max[x]=k;
            return;
        }
        int mid=l+r>>1;
        if(L<=mid) update(x<<1,l,mid,L,R,k);
        if(R>mid)  update(x<<1|1,mid+1,r,L,R,k);
        pushup(x);
    }
    
    int query_Sum(int x,int l,int r,int L,int R){
        if(L<=l && r<=R) return sum[x];
        int mid=l+r>>1,ret=0;
        if(L<=mid) ret+=query_Sum(x<<1,l,mid,L,R);
        if(R>mid)  ret+=query_Sum(x<<1|1,mid+1,r,L,R);
        return ret;
    }
    
    int query_Max(int x,int l,int r,int L,int R){
        if(L<=l && r<=R) return Max[x];
        int mid=l+r>>1,ret=-30001;
        if(L<=mid) ret=max(ret,query_Max(x<<1,l,mid,L,R));
        if(R>mid)  ret=max(ret,query_Max(x<<1|1,mid+1,r,L,R));
        return ret;
    }
    
    //---------------------------------------------------------
    
    int qMax(int x,int y){
        int ret=-30001;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ret=max(ret,query_Max(1,1,n,id[top[x]],id[x]));
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        ret=max(ret,query_Max(1,1,n,id[x],id[y]));
        return ret;
    }
    
    int qSum(int x,int y){
        int ret=0;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ret+=query_Sum(1,1,n,id[top[x]],id[x]);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        ret+=query_Sum(1,1,n,id[x],id[y]);
        return ret;
    }
    
    int main(){
        n=rd();
        int x,y;char c[15];
        for(register int i=1;i<n;i++){
            x=rd(),y=rd();
            add(x,y),add(y,x);
        }
        for(register int i=1;i<=n;i++) a[i]=rd();
        dfs1(1,0,1),dfs2(1,1);
        build(1,1,n);
        m=rd();
        while(m--){
            scanf("%s",c+1);
            if(c[2]=='M'){
                x=rd(),y=rd();
                printf("%d
    ",qMax(x,y));
            }
            else if(c[2]=='S'){
                x=rd(),y=rd();
                printf("%d
    ",qSum(x,y));
            }
            else {
                x=rd(),y=rd();
                update(1,1,n,id[x],id[x],y);
            }
        }
        return 0;
    }
  • 相关阅读:
    微信小程序配置域名的时候提示“校验文件验证失败”
    微信小程序封装mixins方法
    nuxt中报window is not defined
    nuxt中iview按需加载配置
    nuxt 项目安装及环境配置
    使用指针遍历图像
    图像添加噪声(椒盐噪声)
    Java中基本知识梳理【定时器实现多线程】-----2015年3月15日
    Java基础知识---【静态成员,封装性,包】------2015年3月6日
    Java中基本知识梳理【基本变量的处理】-----2015年3月6日
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676845.html
Copyright © 2011-2022 走看看