Tree chain split (hdu3966)

Meaning of the questions:
multiple sets of data.
n barracks, m road, q operations.
"I": to all barracks on the C1 and C2 roads have increased the K soldier;
"D": to all barracks on the C1 and C2 roads have reduced the K soldier;
"Q": Query on the K barracks of people.

Really Finally, finally put this program to the tune before.
Topic <-
Let's talk about the tree split chain;
As for dfs1 and dfs2, look at this God Ben's blog <portal>
Here with me to talk about the tree line to defend this question.
Change Function:
1. When they when not on the same heavy chain, the point is not the same heavy weight of his own son moved to the heavy chain of the father go (of course, while improved, still while maintenance) continued the upward lift until they are in the same heavy chain .
2. When they are in the same heavy chain, which is easy to handle, these two points directly maintain the interval formed at a position in the heavy chain (corresponding to the data structure (the title is a segment tree)).

/*
size[]数组,用来保存以x为根的子树节点个数
top[]数组,用来保存当前节点的所在链的顶端节点
son[]数组,用来保存重儿子
dep[]数组,用来保存当前节点的深度
fa[]数组,用来保存当前节点的父亲
tid[]数组,用来保存树中每个节点剖分后的新编号
rank[]数组,用来保存当前节点在线段树中的位置
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define ak(aa) memset(aa,0,sizeof(aa))
#define begin Begin 
#define to To
#define next Next 
#define rank Rank
#define size Size
#define lr node<<1
#define rr node<<1|1
using namespace std;
const int maxn=50010;
int n,m,q,sum;
int begin[maxn<<1],to[maxn<<1],next[maxn<<1],e;
int a[maxn];
int dep[maxn<<1],top[maxn<<1],rank[maxn<<1],son[maxn<<1],fa[maxn<<1],tid[maxn<<1],size[maxn<<1];
int lazy[maxn<<2],tree[maxn<<2];

struct tree_chain_partition{
    void add(int x,int y){
        to[++e]=y,next[e]=begin[x],begin[x]=e;
        to[++e]=x,next[e]=begin[y],begin[y]=e;
    }

    void dfs1(int node,int father,int d){
        dep[node]=d;
        fa[node]=father;
        size[node]=1;
        for(int i=begin[node];i;i=next[i]){
            int u=to[i];
            if(u!=father){//无向图处理
                dfs1(u,node,d+1);
                size[node]+=size[u];
                /*记录重儿子*/
                if(son[node]==-1 || size[u]>size[son[node]]) son[node]=u;
            }
        }
    }

    void dfs2(int node,int t){
        top[node]=t;
        tid[node]=++sum;
        rank[tid[node]]=node;
        if(son[node]==-1) return ;
        /*便利重链*/
        dfs2(son[node],t);
        for(int i=begin[node];i;i=next[i]){
            int u=to[i];
            /*轻链*/
            if(u!=son[node] && u!=fa[node]){
                dfs2(u,u);//开辟重链 
            }
        }
    }

    void create_tree(int node,int l,int r){
        lazy[node]=0;
        if(l==r){
            tree[node]=a[rank[l]];
            return ;
        }
        int mid=(l+r)>>1;
        create_tree(lr,l,mid);
        create_tree(rr,mid+1,r);
        tree[node]=tree[lr]+tree[rr];//在本题中毫无意义
    }

    void down(int node,int l,int r){
        if(!lazy[node]) return ;
        int mid=(l+r)>>1;
        tree[lr]+=(mid-l+1)*lazy[node];
        tree[rr]+=(r-mid)*lazy[node];
        lazy[lr]+=lazy[node];
        lazy[rr]+=lazy[node];
        lazy[node]=0;
        return ;
    }

    void update(int node,int l,int r,int be,int en,int ad){
        if(be<=l && en>=r){
            lazy[node]+=ad;
            tree[node]+=(r-l+1)*ad;
            return ;
        }
        down(node,l,r);
        int mid=(l+r)>>1;
        if(be<=mid) update(lr,l,mid,be,en,ad);
        if(mid<en) update(rr,mid+1,r,be,en,ad);
        tree[node]=tree[lr]+tree[rr];
        return ;
    }

    int query(int node,int l,int r,int be,int en){
        if(be<=l && en>=r){
            return tree[node];
        }
        down(node,l,r);
        int mid=(l+r)>>1,md=0;
        if(be<=mid) md+=query(lr,l,mid,be,en);
        if(mid<en) md+=query(rr,mid+1,r,be,en);
        tree[node]=tree[lr]+tree[rr];
        return md;
    }

    void change(int l,int r,int mdzz){
        /*不同重链中*/
        while(top[l]!=top[r]){
            if(dep[top[l]]<dep[top[r]]) swap(l,r);//深的优先
            update(1,1,n,tid[top[l]],tid[l],mdzz);//维护这一个区间
            l=fa[top[l]];//提上去到另一条重链
        }
        /*同一重链中*/
        if(dep[l]>dep[r]) swap(l,r);//保证序列
        update(1,1,n,tid[l],tid[r],mdzz);
        return ;
    }

    void init(){
        ak(tree);
        memset(begin,0,sizeof(begin));
        memset(son,-1,sizeof(son));
        e=0;sum=0;
    }

    void work(){
        init();
        For(i,1,n){
            scanf("%d",&a[i]);
        }
        For(i,1,m){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        dfs1(1,1,0);
        dfs2(1,1);
        create_tree(1,1,n);
        For(i,1,q){
            char s[2];
            scanf("%s",s);
            if(s[0]=='Q'){
                int x;
                scanf("%d",&x);
                printf("%d\n",query(1,1,n,tid[x],tid[x]));
            }else{
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                if(s[0]=='D') z=-z;
                change(x,y,z);
            }
        }
        return ;
    }
}d;

int main(){
    while(~scanf("%d%d%d",&n,&m,&q)) d.work();
    return 0;
}
Published 51 original articles · won praise 6 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_35776579/article/details/54428503