zoukankan      html  css  js  c++  java
  • 【BZOJ1036/ZJOI2008】树的统计(Count)-树链剖分

    Problem 树的统计

    题目大意

    一棵树上有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本身

    So Lazy No Solution

    裸的树链剖分,题解一搜一大把。就连这个都炸了几次。我太菜了。。。

    AC Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <climits>
    #define lc now<<1
    using namespace std;
    struct SGTree{
        int val,sum,mx;
    }tr[120010];
    struct Node{
        int to,next;
    }a[60010];
    int tot=0,dtot=0,x,n,m,h[30010],dep[30010],up[30010],size[30010];
    int dfn[30010],rk[30010],fa[30010],val[30010],son[30010];
    char tsk[10];
    int dfs_sz(int now,int father,int depth){
        dep[now]=depth;
        fa[now]=father;
        int maxs=0,maxn=0;
        for(int i=h[now];~i;i=a[i].next)
            if(a[i].to!=father)
                size[now]+=dfs_sz(a[i].to,now,depth+1),
                maxs=max(size[a[i].to],maxs),
                maxn=(maxs==size[a[i].to])?a[i].to:maxn;
        son[now]=(maxn==0)?-1:maxn;
        size[now]++;
        return size[now];
    }
    void dfs_son(int now,int upest){
        dfn[now]=++dtot;
        rk[dtot]=now;
        up[now]=upest;
        if(son[now]==-1)return;
        dfs_son(son[now],upest);
        for(int i=h[now];~i;i=a[i].next)
            if(a[i].to!=fa[now]&&a[i].to!=son[now])
                dfs_son(a[i].to,a[i].to);
    }
    void add(int u,int v){
        a[++tot].to=v;a[tot].next=h[u];h[u]=tot;
        a[++tot].to=u;a[tot].next=h[v];h[v]=tot;
    }
    void build(int l,int r,int now){
        if(l==r){
            tr[now].mx=tr[now].val=tr[now].sum=val[rk[l]];
            return;
        }
        int mid=(l+r)>>1;
        tr[lc].mx=-INT_MAX,tr[(lc)+1].mx=-INT_MAX;
        build(l,mid,lc);
        build(mid+1,r,(lc)+1);
        tr[now].mx=max(tr[lc].mx,tr[(lc)+1].mx);
        tr[now].sum=tr[lc].sum+tr[(lc)+1].sum;
    }
    int sgt_max(int s,int t,int l,int r,int now){
        if(l==s&&r==t)return tr[now].mx;
        int mid=(l+r)>>1;
        if(t<=mid)return sgt_max(s,t,l,mid,lc);
        else if(mid<s)return sgt_max(s,t,mid+1,r,(lc)+1);
        else return max(sgt_max(s,mid,l,mid,lc),sgt_max(mid+1,t,mid+1,r,(lc)+1)); 
    }
    int sgt_sum(int s,int t,int l,int r,int now){
        if(l==s&&r==t)return tr[now].sum;
        int mid=(l+r)>>1;
        if(t<=mid)return sgt_sum(s,t,l,mid,lc);
        else if(mid<s)return sgt_sum(s,t,mid+1,r,(lc)+1);
        else return sgt_sum(s,mid,l,mid,lc)+sgt_sum(mid+1,t,mid+1,r,(lc)+1); 
    }
    int query_max(int s,int t){
        int u=up[s],v=up[t],ret=-INT_MAX;
        while(u!=v){
            if(dep[u]<dep[v])swap(u,v),swap(s,t);
            ret=max(ret,sgt_max(dfn[u],dfn[s],1,dtot,1));
            s=fa[u];
            u=up[s];
        }
        if(dep[s]>dep[t])swap(s,t);
        ret=max(ret,sgt_max(dfn[s],dfn[t],1,dtot,1));
        return ret;
    }
    int query_sum(int s,int t){
        int u=up[s],v=up[t],ret=0;
        while(u!=v){
            if(dep[u]<dep[v])swap(u,v),swap(s,t);
            ret+=sgt_sum(dfn[u],dfn[s],1,dtot,1);
            s=fa[u];
            u=up[s];
        }
        if(dep[s]>dep[t])swap(s,t);
        ret+=sgt_sum(dfn[s],dfn[t],1,dtot,1);
        return ret;
    }
    void change(int u,int x,int l,int r,int now){
        if(l==r&&l==u){
            tr[now].val=tr[now].mx=tr[now].sum=x;
            return;
        }
        int mid=(l+r)>>1;
        if(u<=mid)change(u,x,l,mid,lc);
        else change(u,x,mid+1,r,(lc)+1);
        tr[now].mx=max(tr[lc].mx,tr[(lc)+1].mx);
        tr[now].sum=tr[lc].sum+tr[(lc)+1].sum;}
    int main(){
    //  freopen("bzoj1036.in","r",stdin);
        memset(h,-1,sizeof(h));
        int u,v;
        scanf("%d",&n);
        for(int i=1;i<n;i++)
            scanf("%d%d",&u,&v),
            add(u,v);
        dfs_sz(1,0,0);
        dfs_son(1,1);
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        build(1,dtot,1);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%s",tsk);
            if(tsk[0]=='Q'&&tsk[1]=='M')
                scanf("%d%d",&u,&v),
                printf("%d
    ",query_max(u,v));
            else if(tsk[0]=='Q'&&tsk[1]=='S')
                scanf("%d%d",&u,&v),
                printf("%d
    ",query_sum(u,v));
            else if(tsk[0]=='C')
                scanf("%d%d",&u,&x),
                change(dfn[u],x,1,dtot,1);
        }
    }
  • 相关阅读:
    不能成为专业软件测试人员的10大理由
    不能成为专业软件测试人员的10大理由
    团队建设三境界
    团队建设三境界
    团队建设三境界
    界面测试总结
    界面测试总结
    codevs 1220 数字三角形
    codevs 1214 线段覆盖
    codevs 2181 田忌赛马
  • 原文地址:https://www.cnblogs.com/skylynf/p/7327434.html
Copyright © 2011-2022 走看看