[bzoj1036]:[ZJOI2008]树的统计Count(树链剖分)

传送门
十分裸的一个树链剖分,这也是我第一次过树剖题,好激动!
关于这个算法我不多说,自己百度。
代码:

/**************************************************************
    Problem: 1036
    User: stone41123
    Language: C++
    Result: Accepted
    Time:2484 ms
    Memory:5676 kb
****************************************************************/
 
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    int x=0;char ch=' ';int f=1;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
struct edge{
    int to,next;
}e[60001];
int n,tot,q;
int v[30001];
int head[30001];
inline void addedge(int x,int y){
    e[++tot].to=y;e[tot].next=head[x];head[x]=tot;
}
int father[30001];
int size[30001];
int top[30001];
int heavy[30001];
int dep[30001];
void dfs1(int x,int fa){
    father[x]=fa;
    size[x]=1;
    dep[x]=dep[fa]+1;
    for(int i=head[x];i;i=e[i].next){
        int u=e[i].to;
        if(u==fa)continue;
        dfs1(u,x);
        size[x]+=size[u];
        if(size[u]>size[heavy[x]]){
            heavy[x]=u;
        }
    }
}
int a[30001];
int mp[30001];
int cnt;
int id[30001];
void dfs2(int x,int first){
    top[x]=first;
    id[++cnt]=x;
    mp[x]=cnt;
    a[cnt]=v[x];
    if(size[x]==1){
        return;
    }
    dfs2(heavy[x],first);
    for(int i=head[x];i;i=e[i].next){
        int u=e[i].to;
        if(u==heavy[x]||u==father[x]){
            continue;
        }
        dfs2(u,u);
    }
}
int sum[30001*4];
int mx[30001*4];
inline void pushup(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void build(int rt,int l,int r){
    if(l==r){
        sum[rt]=mx[rt]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int pos,int x){
    if(l==r){
        sum[rt]=mx[rt]=x;
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)update(rt<<1,l,mid,pos,x);
    else update(rt<<1|1,mid+1,r,pos,x);
    pushup(rt);
}
int qmax(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        return mx[rt];
    }
    int mid=(l+r)>>1;
    int ans=-0x7fffffff;
    if(L<=mid)ans=max(ans,qmax(rt<<1,l,mid,L,R));
    if(mid+1<=R)ans=max(ans,qmax(rt<<1|1,mid+1,r,L,R));
    return ans;
}
int qsum(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        return sum[rt];
    }
    int mid=(l+r)>>1;
    int ans=0;
    if(L<=mid)ans+=qsum(rt<<1,l,mid,L,R);
    if(mid+1<=R)ans+=qsum(rt<<1|1,mid+1,r,L,R);
    return ans;
}
int query_max(int x,int y){
    int ans=-0x7fffffff;
    int tx=top[x];
    int ty=top[y];
    while(tx!=ty){
        if(dep[tx]<dep[ty]){
            swap(x,y);swap(tx,ty);
        }
        ans=max(ans,qmax(1,1,n,mp[tx],mp[x]));
        x=father[tx];
        tx=top[x];
    }
    if(dep[x]<dep[y]){
        swap(x,y);swap(tx,ty);
    }
    return max(ans,qmax(1,1,n,mp[y],mp[x]));
}
int query_sum(int x,int y){
    int ans=0;
    int tx=top[x];
    int ty=top[y];
    while(tx!=ty){
        if(dep[tx]<dep[ty]){
            swap(x,y);swap(tx,ty);
        }
        ans+=qsum(1,1,n,mp[tx],mp[x]);
        x=father[tx];
        tx=top[x];
    }
    if(dep[x]<dep[y]){
        swap(x,y);swap(tx,ty);
    }
    return ans+qsum(1,1,n,mp[y],mp[x]);
}
int main(){
    n=read();
    for(int i=1;i<n;i++){
        int x=read(),y=read();
        addedge(x,y);addedge(y,x);
    }
    for(int i=1;i<=n;i++)v[i]=read();
    q=read();
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    char cmp0[20]="CHANGE";
    char cmp1[20]="QMAX";
    char cmp2[20]="QSUM";
    for(int i=1;i<=q;i++){
        char s[20];
        scanf("%s",s);
        if(strcmp(cmp0,s)==0){
            int pos=read(),x=read();
            update(1,1,n,mp[pos],x);
        }
        else if(strcmp(cmp1,s)==0){
            int x=read(),y=read();
            printf("%d\n",query_max(x,y));
        }
        else{
            int x=read(),y=read();
            printf("%d\n",query_sum(x,y));
        }
    }
    return 0;
}
posted @ 2017-09-27 12:06  玫葵之蝶  阅读(233)  评论(0编辑  收藏  举报