bzoj1036 树链剖分模板

模板题,,复习一波。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int n,m;
const int N=1e5+5;
struct node
{
    int l,r,mx,sum;
}t[N];
int head[N],next[N],go[N],val[N];
int siz[N],dep[N],fa[N];
int pos[N],bl[N],v[N];
int cnt=0;
int sz;
inline void add(int x,int y)
{
    go[++cnt]=y;
    next[cnt]=head[x];
    head[x]=cnt;
}
inline void dfs1(int x)
{
    siz[x]=1;
    int i=head[x];
    while(i)
    {
        int v=go[i];
        if (v!=fa[x])
        {
            dep[v]=dep[x]+1;
            fa[v]=x;
            dfs1(v);
            siz[x]+=siz[v];
        }
        i=next[i];
    }
}
inline void dfs2(int x,int top)
{
    int k=0;sz++;
    pos[x]=sz;
    bl[x]=top;
    int i=head[x];
    while (i)
    {
        int v=go[i];
        if (dep[v]>dep[x]&&siz[v]>siz[k])
        k=v;
        i=next[i];
    }
    if (!k)return;
    dfs2(k,top);
    i=head[x];
    while (i)
    {
        int v=go[i];
        if (dep[v]>dep[x]&&k!=v)
        {
            dfs2(v,v);
        }
        i=next[i];
    }
}
inline void build(int x,int l,int r)
{
    t[x].l=l;
    t[x].r=r;
    if (l==r)return;
    int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
}
inline void change(int x,int pos,int v)
{
    if(t[x].l==t[x].r)
    {
        t[x].sum=t[x].mx=v;
        return;
    }
    int mid=(t[x].l+t[x].r)>>1;
    if (pos<=mid)change(x<<1,pos,v);
    else change(x<<1|1,pos,v);
    t[x].sum=(t[x<<1].sum+t[x<<1|1].sum);
    t[x].mx=max(t[x<<1].mx,t[x<<1|1].mx);
}
inline int querysum(int k,int x,int y)
{
    if (t[k].l==x&&t[k].r==y)return t[k].sum;
    int mid=(t[k].l+t[k].r)>>1;
    if (y<=mid)return querysum(k<<1,x,y);
    else if (x>mid)return querysum(k<<1|1,x,y);
    else return querysum(k<<1,x,mid)+querysum(k<<1|1,mid+1,y);
}
inline int querymx(int k,int x,int y)
{
    if (t[k].l==x&&t[k].r==y)return t[k].mx;
        int mid=(t[k].l+t[k].r)>>1;
    if (y<=mid)return querymx(k<<1,x,y);
    else if (x>mid)return querymx(k<<1|1,x,y);
    else return max(querymx(k<<1,x,mid),querymx(k<<1|1,mid+1,y));
}
inline int solvesum(int x,int y)
{
    int sum=0;
    while (bl[x]!=bl[y])
    {
        if (dep[bl[x]]<dep[bl[y]])swap(x,y);
        sum+=querysum(1,pos[bl[x]],pos[x]);
        x=fa[bl[x]];
    }
    if (pos[x]>pos[y])swap(x,y);
    sum+=querysum(1,pos[x],pos[y]);
    return sum;
}
const int inf=1e9;
inline int solvemx(int x,int y)
{
    int mx=-inf;
    while (bl[x]!=bl[y])
    {
        if (dep[bl[x]]<dep[bl[y]])swap(x,y);
        mx=max(mx,querymx(1,pos[bl[x]],pos[x]));
        x=fa[bl[x]];
    }
    if (pos[x]>pos[y])swap(x,y);
    mx=max(mx,querymx(1,pos[x],pos[y]));
    return mx;
}
inline void solve()
{
    build(1,1,n);
    fo(i,1,n)change(1,pos[i],v[i]);
    int q;
    scanf("%d",&q);
    char ch[5];
    fo(i,1,q)
    {
        int x,y;
        scanf("%s%d%d",&ch,&x,&y);
        if (ch[0]=='C')
        {
            v[x]=y;
            change(1,pos[x],y);
        }
        else 
        {
            if (ch[1]=='M')printf("%d\n",solvemx(x,y));
            else printf("%d\n",solvesum(x,y));
        }
    }
}
int main()
{
    scanf("%d",&n);
    fo(i,1,n-1)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    fo(i,1,n)scanf("%d",&v[i]);
    dfs1(1);
    dfs2(1,1);
    solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值