树链剖分+线段树模板 [BZOJ][1036][ZJOI2008]树的统计Count

#include<bits/stdc++.h>
using namespace std;
 
const int MAXN=30000+233;
const int INF=0x3f3f3f3f;
 
struct Edge {
    int to,nxt;
} e[MAXN<<2];
 
int n,q,x,y,cnt=0,dfnt=0;
int head[MAXN],val[MAXN];
int dep[MAXN],siz[MAXN],fa[MAXN],son[MAXN],tp[MAXN],pos[MAXN];
char opt[233];
 
int read() {
    int x=0,f=1;
    char ch=getchar();
    while (!isdigit(ch)) {
        if (ch=='-')
            f=-1;
        ch=getchar();
    }
    while (isdigit(ch))
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
 
void add_edge(int u,int v) {
    e[++cnt].nxt=head[u];
    head[u]=cnt;
    e[cnt].to=v;
}
 
void dfs1(int x) {
    siz[x]=1;
    for (int i=head[x]; i; i=e[i].nxt) {
        int v=e[i].to;
        if (v!=fa[x]) {
            fa[v]=x;
            dep[v]=dep[x]+1;
            dfs1(v);
            siz[x]+=siz[v];
            if (!son[x]||siz[v]>siz[son[x]])
                son[x]=v;
        }
    }
}
 
void dfs2(int x,int TOP) {
    pos[x]=++dfnt;
    tp[x]=TOP;
    if (!son[x])
        return;
    dfs2(son[x],TOP);
    for (int i=head[x]; i; i=e[i].nxt) {
        int v=e[i].to;
        if (v!=son[x]&&v!=fa[x])
            dfs2(v,v);
    }
}
 
namespace Segment_Tree {
    struct Tree {
        int sum,mt;
    } t[MAXN<<3];
    void push_up(int root) {
        t[root].sum=t[root<<1].sum+t[root<<1|1].sum;
        t[root].mt=max(t[root<<1].mt,t[root<<1|1].mt);
    }
    void update(int root,int l,int r,int qt,int dat) {
        if (l==r) {
            t[root].mt=t[root].sum=dat;
            return;
        }
        int mid=l+r>>1;
        if (qt<=mid)
            update(root<<1,l,mid,qt,dat);
        else
            update(root<<1|1,mid+1,r,qt,dat);
        push_up(root);
    }
    long long query_max(int root,int l,int r,int ql,int qr) {
        if (ql<=l&&qr>=r)
            return t[root].mt;
        long long ans=-INF;
        int mid=l+r>>1;
        if (ql<=mid)
            ans=max(ans,query_max(root<<1,l,mid,ql,qr));
        if (qr>mid)
            ans=max(ans,query_max(root<<1|1,mid+1,r,ql,qr));
        return ans;
    }
    long long query_sum(int root,int l,int r,int ql,int qr) {
        if (ql<=l&&qr>=r)
            return t[root].sum;
        long long ans=0;
        int mid=l+r>>1;
        if (ql<=mid)
            ans+=query_sum(root<<1,l,mid,ql,qr);
        if (qr>mid)
            ans+=query_sum(root<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    long long Solve_max(int l,int r) {
        long long ans=-INF;
        for (; tp[x]!=tp[y]; x=fa[tp[x]]) {
            if (dep[tp[x]]<dep[tp[y]])
                swap(x,y);
            ans=max(ans,query_max(1,1,n,pos[tp[x]],pos[x]));
        }
        if (dep[x]<dep[y])
            swap(x,y);
        ans=max(ans,query_max(1,1,n,pos[y],pos[x]));
        return ans;
    }
    long long Solve_sum(int l,int r) {
        long long ans=0;
        for (; tp[x]!=tp[y]; x=fa[tp[x]]) {
            if (dep[tp[x]]<dep[tp[y]])
                swap(x,y);
            ans+=query_sum(1,1,n,pos[tp[x]],pos[x]);
        }
        if (dep[x]<dep[y])
            swap(x,y);
        ans+=query_sum(1,1,n,pos[y],pos[x]);
        return ans;
    }
    void build_tree(int l,int r) {
        for (int i=l; i<=r; i++)
            update(1,1,n,pos[i],val[i]);
    }
}
using namespace Segment_Tree;
 
int main() {
    n=read();
    for (int i=1,u,v; i<n; i++)
        u=read(),v=read(),add_edge(u,v),add_edge(v,u);
    for (int i=1; i<=n; i++)
        val[i]=read();
    dfs1(1);
    dfs2(1,1);
    build_tree(1,n);
    q=read();
    while (q--) {
        scanf("%s%d%d",opt+1,&x,&y);
        if (opt[1]=='C')
            update(1,1,n,pos[x],y);
        else if (opt[2]=='M')
            printf("%lld\n",Solve_max(x,y));
        else if (opt[2]=='S')
            printf("%lld\n",Solve_sum(x,y));
    }
    return 0;
}

 

posted @ 2018-08-24 12:37  QingCai_DCF  阅读(123)  评论(0编辑  收藏  举报