BZOJ1037 ZJOI2008 树的统计 树链剖分

题意:给定一棵树,维护:1、将u的权值修改为v  2、求u到v路径上的最大权  3、求u到v路径上的点权和

题解:树链剖分裸题

#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=100000+2;
struct HASH{
    int u;
    HASH *next;
    HASH(){}
    HASH(int _u,HASH *_next):u(_u),next(_next){}
}mem[2*MAXN];
struct NODE{
    int v,son,f,c,depth,belong,mark;
    HASH *child;
}node[MAXN];
typedef struct TREE{
    int v,s,l,r,same;
    TREE *lchild,*rchild;
    TREE(){}
    TREE(int _l,int _r):l(_l),r(_r),s(0),same(INT_MIN),lchild(0),rchild(0){}
} *ROOT;
ROOT root;
int N,Q,cnt,mark[MAXN];
char s[8+2];

void Insert(int u,int v){ node[u].child=&(mem[cnt++]=HASH(v,node[u].child));}

void DFS1(int x,int f,int d){
    node[x].f=f,node[x].depth=d,node[x].c=1;

    for(HASH *p=node[x].child;p;p=p->next)
        if(p->u!=f){
            DFS1(p->u,x,d+1);
            node[x].c+=node[p->u].c;
            if(!node[x].son || node[p->u].c>node[node[x].son].c) node[x].son=p->u;
        }
}

void DFS2(int x,int b){
    node[x].belong=b,node[x].mark=++cnt,mark[cnt]=x;
    if(!node[x].son) return;
    DFS2(node[x].son,b);
    for(HASH *p=node[x].child;p;p=p->next)
        if(p->u!=node[x].f && p->u!=node[x].son) DFS2(p->u,p->u);
}

void Pushup(ROOT &x){
    x->s=x->lchild->s+x->rchild->s;
    x->v=max(x->lchild->v,x->rchild->v);
}

void Pushdown(ROOT &x,int m){
    if(x->same!=INT_MIN){
        x->lchild->v=x->rchild->v=x->same;
        x->lchild->same=x->rchild->same=x->same;
        x->lchild->s=x->same*(m-(m>>1));
        x->rchild->s=x->same*(m>>1);
        x->same=INT_MIN;
    }
}

void Build(ROOT &x,int l,int r){
    x=new TREE(l,r);
    if(l==r){
        x->s=x->v=node[mark[l]].v;
        return;
    }

    int m=(l+r)>>1;
    Build(x->lchild,l,m),Build(x->rchild,m+1,r);

    Pushup(x);
}

void Change(ROOT &x,int p,int v){
    if(x->l==x->r){
        x->v=x->same=v,x->s=v*(x->r-x->l+1);
        return;
    }

    Pushdown(x,x->r-x->l+1);

    int m=(x->l+x->r)>>1;
    if(p<=m) Change(x->lchild,p,v);
    else Change(x->rchild,p,v);

    Pushup(x);
}

int Find_Max(ROOT &x,int l,int r){
    if(x->l>=l && x->r<=r) return x->v;

    Pushdown(x,x->r-x->l+1);

    int m=(x->l+x->r)>>1,ret=INT_MIN;
    if(l<=m) ret=max(ret,Find_Max(x->lchild,l,r));
    if(r>m) ret=max(ret,Find_Max(x->rchild,l,r));

    return ret;
}

int Get_Max(int u,int v){
    int ret=INT_MIN;
    while(node[u].belong!=node[v].belong){
        if(node[node[u].belong].depth<node[node[v].belong].depth) swap(u,v);
        ret=max(ret,Find_Max(root,node[node[u].belong].mark,node[u].mark));
        u=node[node[u].belong].f;
    }

    if(node[u].depth<node[v].depth) swap(u,v);
    ret=max(ret,Find_Max(root,node[v].mark,node[u].mark));

    return ret;
}

int Find_Sum(ROOT &x,int l,int r){
    if(x->l>=l && x->r<=r) return x->s;

    Pushdown(x,x->r-x->l+1);

    int m=(x->l+x->r)>>1,ret=0;
    if(l<=m) ret+=Find_Sum(x->lchild,l,r);
    if(r>m) ret+=Find_Sum(x->rchild,l,r);

    return ret;
}

int Get_Sum(int u,int v){
    int ret=0;
    while(node[u].belong!=node[v].belong){
        if(node[node[u].belong].depth<node[node[v].belong].depth) swap(u,v);
        ret+=Find_Sum(root,node[node[u].belong].mark,node[u].mark);
        u=node[node[u].belong].f;
    }

    if(node[u].depth<node[v].depth) swap(u,v);
    ret+=Find_Sum(root,node[v].mark,node[u].mark);

    return ret;
}

int main(){
    memset(node,0,sizeof(node));
    cnt=0;

    cin >> N;
    for(int i=1,u,v;i<N;i++){
        cin >> u >> v;
        Insert(u,v),Insert(v,u);
    }
    for(int i=1;i<=N;i++) cin >> node[i].v;

    cnt=0,DFS1(1,0,0),DFS2(1,1);
    Build(root,1,cnt);

    cin >> Q;
    for(int i=1,a,b;i<=Q;i++){
        scanf("%s %d %d",s,&a,&b);
        if(strstr(s,"QMAX")) cout << Get_Max(a,b) << endl;
        if(strstr(s,"QSUM")) cout << Get_Sum(a,b) << endl;
        if(strstr(s,"CHANGE")) Change(root,node[a].mark,b);
    }

    return 0;
}
View Code

 

posted @ 2017-02-26 13:24  WDZRMPCBIT  阅读(167)  评论(0编辑  收藏  举报