BZOJ 1036: [ZJOI2008]树的统计Count【树链剖分】

1036: [ZJOI2008]树的统计Count

【题目描述】
传送门

【题解】

裸的树链剖分。

代码如下

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 30005
using namespace std;
int n,m,a[MAXN],W[MAXN];
int Tre[MAXN<<2],MT[MAXN<<2],Add[MAXN<<2];
int cnt,Son[MAXN],Siz[MAXN],Fa[MAXN],ID[MAXN],Dep[MAXN],Top[MAXN];
struct Edge{
    int tot,son[MAXN<<1],nxt[MAXN<<1],lnk[MAXN];
    void Add(int x,int y){son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;}
}E;
void First(int x,int f,int D){
    Siz[x]=1;Dep[x]=D;Fa[x]=f;
    for(int j=E.lnk[x],NowSize=0;j;j=E.nxt[j])
    if(E.son[j]^f){
        First(E.son[j],x,D+1),Siz[x]+=Siz[E.son[j]];
        if(Siz[E.son[j]]>NowSize) NowSize=Siz[E.son[j]],Son[x]=E.son[j];
    }
}
void Second(int x,int T){
    ID[x]=++cnt;Top[x]=T;W[cnt]=a[x];
    if(!Son[x]) return;Second(Son[x],T);
    for(int j=E.lnk[x];j;j=E.nxt[j])
    if(!ID[E.son[j]]) Second(E.son[j],E.son[j]);
}
void Build(int x,int l,int r){
    if(l==r){Tre[x]=MT[x]=W[l];return;}
    int mid=(r+l)>>1;
    Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
    Tre[x]=Tre[x<<1]+Tre[x<<1|1];MT[x]=max(MT[x<<1],MT[x<<1|1]);
}
void Updata(int x,int l,int r,int k,int p){
    if(l==r){Tre[x]=MT[x]=p;return;}
    int mid=(r+l)>>1;
    if(k<=mid) Updata(x<<1,l,mid,k,p);else Updata(x<<1|1,mid+1,r,k,p);
    Tre[x]=Tre[x<<1]+Tre[x<<1|1];MT[x]=max(MT[x<<1],MT[x<<1|1]);
}
int Query_Sum(int x,int l,int r,int L,int R){
    if(L<=l&&r<=R) return Tre[x];
    int mid=(r+l)>>1,Sum=0;
    if(L<=mid) Sum+=Query_Sum(x<<1,l,mid,L,R);
    if(R>mid) Sum+=Query_Sum(x<<1|1,mid+1,r,L,R);
    return Sum;
}
int Query_Max(int x,int l,int r,int L,int R){
    if(L<=l&&r<=R) return MT[x];
    int mid=(r+l)>>1,Sum=-1e9;
    if(L<=mid) Sum=max(Query_Max(x<<1,l,mid,L,R),Sum);
    if(R>mid) Sum=max(Query_Max(x<<1|1,mid+1,r,L,R),Sum);
    return Sum;
}
int Ask_Sum(int x,int y){
    int Sum=0;
    while(Top[x]^Top[y]){
        if(Dep[Top[x]]>Dep[Top[y]]) swap(x,y);
        Sum+=Query_Sum(1,1,n,ID[Top[y]],ID[y]);y=Fa[Top[y]];
    }
    if(Dep[x]>Dep[y]) swap(x,y);
    Sum+=Query_Sum(1,1,n,ID[x],ID[y]);
    return Sum;
}
int Ask_Max(int x,int y){
    int Sum=-1e9;
    while(Top[x]^Top[y]){
        if(Dep[Top[x]]>Dep[Top[y]]) swap(x,y);
        Sum=max(Sum,Query_Max(1,1,n,ID[Top[y]],ID[y]));y=Fa[Top[y]];
    }
    if(Dep[x]>Dep[y]) swap(x,y);
    Sum=max(Query_Max(1,1,n,ID[x],ID[y]),Sum);
    return Sum;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("prob.in","r",stdin);
    freopen("prob.out","w",stdout);
    #endif
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;scanf("%d%d",&x,&y);
        E.Add(x,y);E.Add(y,x);
    }
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    scanf("%d",&m);
    First(1,0,1);Second(1,1);Build(1,1,n);
    for(int i=1;i<=m;i++){
        char ch[15];scanf("%s",ch);
        int x,y;scanf("%d%d",&x,&y);
        if(ch[1]=='M') printf("%d\n",Ask_Max(x,y));else
        if(ch[1]=='S') printf("%d\n",Ask_Sum(x,y));else Updata(1,1,n,ID[x],y);
    }
    return 0;
}
posted @ 2018-06-06 10:35  XSamsara  阅读(134)  评论(0编辑  收藏  举报