zjoi2008 树链剖分

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct my{
    int u,v,next;
};

const int maxn=100000+5;
int cnt;
int nil=1000000000;
my tu[maxn];
int n;
int head[maxn];
int w[maxn*4];
int size[maxn],d[maxn],fa[maxn],woson[maxn],tpos[maxn],pre[maxn],top[maxn];
char f[10];
int sumv[maxn*4],maxv[maxn*4];
int tot;

void myinsert(int u,int v){
     tu[++tot].u=u;
     tu[tot].v=v;
     tu[tot].next=head[u];
     head[u]=tot;
}

int read()
{
    int p,data=0;
    char ch=0;
    while ((ch!='-') && ch<'0' || ch>'9') ch=getchar();
    if (ch=='-')
    {
        p=-1;
        ch=getchar();
    } else p=1;
    while (ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
    return data*p;
}

void dfs1(int u,int f){
     size[u]=1;
     for (int i=head[u];i;i=tu[i].next){
        int v=tu[i].v;
        if(v==f) continue;
        d[v]=d[u]+1;fa[v]=u;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[woson[u]]) woson[u]=v;
     }
}

void dfs2(int u,int frist){
     tpos[u]=++cnt;
     pre[cnt]=u;
     top[u]=frist;
     if(woson[u]) dfs2(woson[u],frist);
     for (int i=head[u];i;i=tu[i].next){
         int v=tu[i].v;
         if(v==fa[u]||v==woson[u]) continue;
         dfs2(v,v);
     }
}

void pushup(int x){
     sumv[x]=sumv[x<<1]+sumv[x<<1|1];
     maxv[x]=max(maxv[x<<1],maxv[x<<1|1]);
}

void build(int st,int l,int r){
     if(l==r){
        sumv[st]=maxv[st]=w[pre[l]];
        return ;
     }
     int mid=(l+r)>>1;
     build(st<<1,l,mid);
     build(st<<1|1,mid+1,r);
     pushup(st);
}

void update(int st,int l,int r,int pos,int c){
     if(l==r){
        sumv[st]=maxv[st]=c;
        return ;
     }
     int mid=(l+r)>>1;
     if(pos<=mid) update(st<<1,l,mid,pos,c);
     else update(st<<1|1,mid+1,r,pos,c);
     pushup(st);
}

int querysum(int st,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        return sumv[st];
    }
    int mid=(l+r)>>1;
    int ans=0;
    if(L<=mid) ans+=querysum(st<<1,l,mid,L,R);
    if(R>mid) ans+=querysum(st<<1|1,mid+1,r,L,R);
    return ans;
}

int qsum(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(d[top[u]]<d[top[v]]) swap(u,v);
        ans+=querysum(1,1,n,tpos[top[u]],tpos[u]);
        u=fa[top[u]];
    }
    if(d[u]<d[v]) swap(u,v);
    ans+=querysum(1,1,n,tpos[v],tpos[u]);
    return ans;
}

int querymax(int st,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        return maxv[st];
    }
    int ans=-nil;
    int mid=(l+r)>>1;
    if(L<=mid) ans=max(ans,querymax(st<<1,l,mid,L,R));
    if(R>mid) ans=max(ans,querymax(st<<1|1,mid+1,r,L,R));
    return ans;
}

int qmax(int u,int v){
    int ans=-nil;
    while(top[u]!=top[v]){
        if(d[top[u]]<d[top[v]]) swap(u,v);
        ans=max(ans,querymax(1,1,n,tpos[top[u]],tpos[u]));
        u=fa[top[u]];
    }
    if(d[u]<d[v]) swap(u,v);
    ans=max(ans,querymax(1,1,n,tpos[v],tpos[u]));
    return ans;
}

int main(){
    //freopen("cout.out","w",stdout);
      n=read();
      int u,v;
      for (int i=1;i<n;i++){
        u=read();
        v=read();
        myinsert(u,v);
        myinsert(v,u);
      }
    for (int i=1;i<=n;i++) w[i]=read();
    int q;
    q=read();
    d[1]=1;fa[1]=1;
    dfs1(1,-1);
    dfs2(1,1);
    build(1,1,n);
    while(q--){
        int x,y;
        scanf("%s",f);
        x=read();
        y=read();
        if(f[1]=='H') update(1,1,n,tpos[x],y);
        if(f[1]=='M') printf("%d\n",qmax(x,y));
        if(f[1]=='S') printf("%d\n",qsum(x,y));
    }
return 0;
}

posted @ 2018-03-01 18:40  lmjer  阅读(154)  评论(0编辑  收藏  举报