BZOJ-1036-(树链剖分+线段树 模板)

题目
在这里插入图片描述

//Problem: 1036  Time Limit: 10 Sec  Memory Limit: 162 MB
//               Time:2508 ms        Memory:5080 kb
#include<cstdio>
#include<cstring>
#include<algorithm>
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
const int N=3e4+5,INF=0x3f3f3f3f;
int head[N],tot,ovo,n;
int top[N],fa[N],dep[N],sz[N],p[N],fp[N],son[N];
struct Edge{int to,nex;}edge[N<<1];
void add(int from,int to){
    edge[++tot]=(Edge){to,head[from]};head[from]=tot;
    edge[++tot]=(Edge){from,head[to]};head[to]=tot;
}
void route(int x){
    sz[x]=1;
    for(int i=head[x];i;i=edge[i].nex){
        int y=edge[i].to;
        if(y==fa[x]) continue;
        dep[y]=dep[x]+1,fa[y]=x;
        route(y),sz[x]+=sz[y];
        if(son[x]==-1||sz[y]>sz[son[x]]) son[x]=y;
    }
}
void getpos(int x,int root){
    top[x]=root,p[x]=++ovo,fp[ovo]=x;
    if(son[x]==-1) return;
    getpos(son[x],root);
    for(int i=head[x];i;i=edge[i].nex){
        int y=edge[i].to;
        if(y!=fa[x]&&y!=son[x]) getpos(y,y);
    }
}
int mmax[N<<2],sum[N<<2],c[N];
void build(int l,int r,int pos){
    if(l==r){
        mmax[pos]=sum[pos]=c[fp[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
    mmax[pos]=max(mmax[pos<<1],mmax[pos<<1|1]);
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
void chanpoint(int n,int val,int l,int r,int pos){
    if(l==r){
        mmax[pos]=sum[pos]=val;
        return;
    }
    int mid=(l+r)>>1;
    if(n<=mid) chanpoint(n,val,l,mid,pos<<1);
    else chanpoint(n,val,mid+1,r,pos<<1|1);
    mmax[pos]=max(mmax[pos<<1],mmax[pos<<1|1]);
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
int querymax(int cl,int cr,int l,int r,int pos){
    if(cl<=l&&r<=cr) return mmax[pos];
    int ans=-INF,mid=(l+r)>>1;
    if(cl<=mid) ans=max(ans,querymax(cl,cr,l,mid,pos<<1));
    if(cr>mid) ans=max(ans,querymax(cl,cr,mid+1,r,pos<<1|1));
    return ans;
}
int querysum(int cl,int cr,int l,int r,int pos){
    if(cl<=l&&r<=cr) return sum[pos];
    int ans=0,mid=(l+r)>>1;
    if(cl<=mid) ans+=querysum(cl,cr,l,mid,pos<<1);
    if(cr>mid) ans+=querysum(cl,cr,mid+1,r,pos<<1|1);
    return ans;
}
int findmax(int x,int y){
    int f1=top[x],f2=top[y],ans=-INF;
    while(f1!=f2){
        if(dep[f1]<dep[f2])
            swap(x,y),swap(f1,f2);
        ans=max(ans,querymax(p[f1],p[x],1,n,1));
        x=fa[f1],f1=top[x];
    }
    if(dep[x]>dep[y]) swap(x,y);
    return max(ans,querymax(p[x],p[y],1,n,1));
}
int findsum(int x,int y){
    int f1=top[x],f2=top[y],ans=0;
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
        ans+=querysum(p[f1],p[x],1,n,1);
        x=fa[f1],f1=top[x];
    }
    if(dep[x]>dep[y]) swap(x,y);
    return ans+=querysum(p[x],p[y],1,n,1);
}
char s[7];
int main(){
    //m(head,0),,tot=0,ovo=0;
    m(son,-1);
    scanf("%d",&n);int q,a,b;
    for(int i=1;i<=n-1;i++)
        scanf("%d%d",&a,&b),add(a,b);
    dep[1]=0,fa[1]=-1,route(1);getpos(1,1);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    build(1,n,1);
    scanf("%d",&q);
    while(q--){
        scanf("%s%d%d",s,&a,&b);
        if(s[1]=='H') chanpoint(p[a],b,1,n,1);
        if(s[1]=='M') printf("%d\n",findmax(a,b));
        if(s[1]=='S') printf("%d\n",findsum(a,b));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值