树的统计count

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define maxn 300000
#define ls x<<1
#define rs x<<1|1
using namespace std;
int n,head[maxn],tot=0,v[maxn],top[maxn],son[maxn],fa[maxn],de[maxn],w[maxn],z,tree1[maxn],tree2[maxn],sz[maxn];
char s[20];
struct eg
{
    int to;
    int nxt;
}b[maxn];
void link(int x,int y)
{
    b[++tot].nxt=head[x];
    b[tot].to=y;
    head[x]=tot;
}
void dfs1(int x,int f)
{
    sz[x]=1,fa[x]=f;
    for (int i=head[x];i!=-1;i=b[i].nxt)
    {
        int t=b[i].to;
        if (t==f) continue;
        de[t]=de[x]+1;
        dfs1(t,x);
        sz[x]+=sz[t];
        if (son[x]==-1||sz[son[x]]<sz[t]) son[x]=t;
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp,w[x]=++z;
    if (son[x]!=-1) dfs2(son[x],tp);
    else return ;
    for (int i=head[x];i!=-1;i=b[i].nxt)
    {
        int t=b[i].to;
        if (t!=fa[x]&&t!=son[x]) dfs2(t,t);
    }
}
void build(int x,int l,int r)
{
    tree2[x]=0,tree1[x]=-900000000;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build (ls,l,mid);
    build (rs,mid+1,r);
}
void updata(int x,int l,int r,int d,int y)
{
    if (l==r&&l==d) 
    {
        tree1[x]=y;
        tree2[x]=y;
        return ;
    }
    int mid=(l+r)>>1;
    if (d<=mid)updata(ls,l,mid,d,y);
    else updata(rs,mid+1,r,d,y);
    tree1[x]=max(tree1[ls],tree1[rs]);
    tree2[x]=tree2[ls]+tree2[rs];
}
int qsum(int x,int l,int r,int ll,int rr)
{
    if (ll==l&&r==rr) return tree2[x];
    int mid=(l+r)>>1;
    if (ll>mid) return qsum(rs,mid+1,r,ll,rr);
    else if (rr<=mid) return qsum(ls,l,mid,ll,rr);
    else return qsum(ls,l,mid,ll,mid)+qsum(rs,mid+1,r,mid+1,rr);
}
int qmax(int x,int l,int r,int ll,int rr)
{
    if (ll==l&&r==rr) return tree1[x];
    int mid=(l+r)>>1;
    if (rr<=mid) return qmax(ls,l,mid,ll,rr);
    else if (ll>mid) return qmax(rs,mid+1,r,ll,rr);
    else return max(qmax(ls,l,mid,ll,mid),qmax(rs,mid+1,r,mid+1,rr));
}
int find(int x,int y,int flag)
{
    if (flag==1)
    {
        int ans=-900000000;
        int f1=top[x],f2=top[y];
        while(f1!=f2)
        {
            if(de[f1]<de[f2]) swap(f1,f2),swap(x,y);
            ans=max(ans,qmax(1,1,z,w[f1],w[x]));
            x=fa[f1],f1=top[x];
        }
        if (de[x]>de[y]) swap(x,y);
        return max(ans,qmax(1,1,z,w[x],w[y]));
    }
    if (flag==2)
    {
        int ans=0;
        int f1=top[x],f2=top[y];
        while (f1!=f2)
        {
            if(de[f1]<de[f2]) swap(f1,f2),swap(x,y);
            ans+=qsum(1,1,z,w[f1],w[x]);
            x=fa[f1],f1=top[x];
        }
        if (de[x]>de[y]) swap(x,y);
        return ans+qsum(1,1,z,w[x],w[y]);
    }
}
int main()
{
    memset(head, -1, sizeof(head));
    memset(son, -1, sizeof(son));
    scanf ("%d",&n);
    for (int i=1;i<n;++i)
    {
        int x,y;
        scanf ("%d%d",&x,&y);
        link(x,y);
        link(y,x);
    }
    for (int i=1;i<=n;++i)
        scanf ("%d",&v[i]);
    de[1]=1;
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,z);
    for (int i=1;i<=n;++i) updata(1,1,z,w[i],v[i]);
    int q;
    scanf("%d",&q);
    for (int i=1;i<=q;++i)
    {
        scanf ("%s",s);
        int x,y;
        scanf ("%d%d",&x,&y);
        if (s[0]=='C')
        updata(1,1,z,w[x],y);
        if (s[1]=='M')
        printf("%d\n",find(x,y,1)); 
        if (s[1]=='S')
        printf("%d\n",find(x,y,2)); 
    }
    return 0;
}

嗯我知道打得很丑然而毕竟是第一个几乎全靠自己的树剖板子吧qaq
诶嘿嘿

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值