bzoj 1036(树链剖分)

传送门
模板题,代码就作为模板扔这儿。
注意:每次query从main函数传参时传x,y不是tid[x],tid[y]

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=30004;
const ll INF=1000000007;
int head[maxn],des[maxn<<1],nxt[maxn<<1],edge=0;
int top[maxn],dep[maxn],fa[maxn],son[maxn],siz[maxn],tid[maxn],rk[maxn],tim=0;
ll sum[maxn<<2],maxx[maxn<<2],num[maxn];
int n,m,q;
inline void adde(int u,int v) {
    des[edge]=v,nxt[edge]=head[u],head[u]=edge++;
    des[edge]=u,nxt[edge]=head[v],head[v]=edge++;
}
inline void dfs1(int p,int father,int d) {
    dep[p]=d,fa[p]=father,siz[p]=1;
    for (int i=head[p];i!=-1;i=nxt[i]) {
        int v=des[i];
        if (v==father) continue;
        dfs1(v,p,d+1);
        siz[p]+=siz[v];
        if (son[p]==-1||siz[v]>siz[son[p]])
            son[p]=v;
    }
}
inline void dfs2(int p,int tp) {
    top[p]=tp,tid[p]=++tim,rk[tid[p]]=p;
    if (son[p]==-1) return ; 
    dfs2(son[p],tp);
    for (int i=head[p];i!=-1;i=nxt[i]) {
        int v=des[i];
        if (v!=fa[p]&&v!=son[p])
            dfs2(v,v);
    }
}

inline void pushup(int rt) {
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
inline void build(int l,int r,int rt) {
    if (l==r) {sum[rt]=maxx[rt]=num[rk[l]];return ;}
    int mid=(l+r)>>1;
    build(lson),build(rson);
    pushup(rt);
}
inline void modify(int l,int r,int rt,int pos,ll val) {
    if (l==r) {sum[rt]=maxx[rt]=val;return ;}
    int mid=(l+r)>>1;
    if (pos<=mid) modify(lson,pos,val);
    else modify(rson,pos,val);
    pushup(rt);
}
inline ll query_max(int l,int r,int rt,int L,int R) {
    if (L<=l&&r<=R) return maxx[rt];
    int mid=(l+r)>>1;ll res=-INF;
    if (L<=mid) res=max(res,query_max(lson,L,R));
    if (mid<R) res=max(res,query_max(rson,L,R));
    return res;
}
inline ll query_sum(int l,int r,int rt,int L,int R) {
    if (L<=l&&r<=R) return sum[rt];
    int mid=(l+r)>>1;ll res=0;
    if (L<=mid) res+=query_sum(lson,L,R);
    if (mid<R) res+=query_sum(rson,L,R);
    return res;
}
inline ll get_max(int x,int y) {
    ll res=-INF;
    while (top[x]!=top[y]) {
        if (tid[top[x]]<tid[top[y]]) x^=y^=x^=y;//tid用作dep 
        res=max(res,query_max(root,tid[top[x]],tid[x]));
        x=fa[top[x]];
    }
    if (tid[x]>tid[y]) swap(x,y);//tid用作dep 
    return max(res,query_max(root,tid[x],tid[y]));
}
inline ll get_sum(int x,int y) {
    ll res=0;
    while (top[x]!=top[y]) {
        if (tid[top[x]]<tid[top[y]]) x^=y^=x^=y;//tid用作dep 
        res+=query_sum(root,tid[top[x]],tid[x]);
        x=fa[top[x]];
    }
    if (tid[x]>tid[y]) swap(x,y);//tid用作dep 
    res+=query_sum(root,tid[x],tid[y]);
    return res;
}
int main() {
    freopen("bzoj 1036.in","r",stdin);
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    scanf("%d",&n);
    for (register int i=1;i<n;++i) {
        int u,v;
        scanf("%d%d",&u,&v);
        adde(u,v);
    }
    dfs1(1,0,1);
    dfs2(1,1);
    for (register int i=1;i<=n;++i) scanf("%lld",&num[i]);
    build(root);
    scanf("%d",&q);
    while (q--) {
        char ss[10];
        int pos,L,R;
        ll val;
        scanf("%s",ss);
        if (ss[0]=='C') {
            scanf("%d%lld",&pos,&val);
            modify(root,tid[pos],val);
        }
        else {
            scanf("%d%d",&L,&R);
            if (ss[1]=='M') printf("%lld\n",get_max(L,R));
            else printf("%lld\n",get_sum(L,R));
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值