NC14649 不存在的树 树剖

再见树剖,写代码四十分钟,debug一小时

#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
typedef  long long ll;
using namespace std;
#define rep(i,j,n) for(ll i=j;i<=n;i++)
#define per(i,j,n) for(ll i=j;i>=n;i--)
typedef unsigned long long ull;
typedef unsigned short us;
const ll INF= 1e17+7;
const ll maxx = 1e5+50;
const double eps=1e-8;
inline bool read(ll &num){char in;bool IsN=false;in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m;
ll head[maxx*2],cnt=0;
ll num=0;
ll top[maxx],son[maxx],size[maxx],id[maxx],fa[maxx];
ll a[maxx];
ll deep[maxx];
ll maxl[maxx*4],sum[maxx*4];
ll wt[maxx];
struct stu
{
    ll to,next;
}A[maxx*2];

void add(ll u,ll v)
{
    A[cnt].to=v;
    A[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs1(ll now,ll f)
{
    fa[now]=f;
    size[now]=1;
    deep[now]=deep[f]+1;
    ll k=0;
    for(ll i=head[now];~i;i=A[i].next)
    {
        ll p=A[i].to;
        if(p!=f)
        {
            dfs1(p,now);
            size[now]+=size[p];
            if(size[p]>k)
            {
                k=size[p];
                son[now]=p;
            }
        }
    }
}
void dfs2(ll now,ll f)
{
    top[now]=f;
    id[now]=++num;
    wt[num]=a[now];
    if(son[now]==0) return ;
    dfs2(son[now],f);
    for(ll i=head[now];~i;i=A[i].next)
    {
        ll p=A[i].to;
        if(p!=fa[now]&&p!=son[now])
        {
            dfs2(p,p);
        }
    }
}
void pushup(ll x)
{
    maxl[x]=max(maxl[x<<1],maxl[x<<1|1]);
    sum[x]=sum[x<<1]+sum[x<<1|1];
}
void build(ll x,ll l,ll r)
{
    if(l==r)
    {
        maxl[x]=wt[l];
        sum[x]=wt[l];
        return ;
    }
    ll mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    pushup(x);
}
void modify(ll x,ll l,ll r,ll k,ll val) //  k=val
{
    if(l==r)
    {
        sum[x]=val;
        maxl[x]=val;
        return ;
    }
    ll mid=(l+r)>>1;
    if(k<=mid)
    modify(x<<1,l,mid,k,val);
    if(k>mid)
    modify(x<<1|1,mid+1,r,k,val);
    pushup(x);
}
ll query0(ll x,ll l,ll r,ll ql,ll qr) // zuidazhi
{
    if(ql<=l&&qr>=r)
    {
        return maxl[x];
    }
    ll ans=-INF;
    ll mid=(l+r)>>1;
    if(ql<=mid) ans=max(ans,query0(x<<1,l,mid,ql,qr));
    if(qr>mid) ans=max(ans,query0(x<<1|1,mid+1,r,ql,qr));
    return ans;
}

ll query1(ll x,ll l,ll r,ll ql,ll qr)
{
    if(ql<=l&&qr>=r)
    {
        return sum[x];
    }
    ll ans=0;
    ll mid=(l+r)>>1;
    if(ql<=mid) ans+=query1(x<<1,l,mid,ql,qr);
    if(qr>mid) ans+=query1(x<<1|1,mid+1,r,ql,qr);
    return ans;
}

ll ask0(ll x,ll y)
{
    ll ans=-INF;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]] )
            swap(x,y);
        ans=max(ans,query0(1,1,n,id[top[x]],id[x] ));
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    ans=max(ans, query0(1,1,n,id[x],id[y]) );
    return ans;
}

ll ask1(ll x,ll y)
{
    ll ans=0;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]] )
            swap(x,y);
        ans+=query1(1,1,n,id[top[x]],id[x] );
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    ans+=query1(1,1,n,id[x],id[y]);
    return ans;
}

int main()
{
    ll t,s,q;
    while(scanf("%lld%lld",&n,&q)!=EOF)
    {
        rep(i,1,n) scanf("%lld",&a[i]);
        rep(i,1,n)
        {
            id[i]=0;
            son[i]=0;
            head[i]=-1;
            size[i]=0;
            top[i]=0;
            deep[i]=0;
        }
        cnt=0;
        num=0;
        ll x,y;
        rep(i,1,n-1)
        {
            scanf("%lld%lld",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs1(1,0);
        dfs2(1,1);
        build(1,1,n);
        ll f;
        while(q--)
        {
            scanf("%lld%lld%lld",&f,&x,&y);
            if(f==0)
            {
                printf("%lld\n",ask0(x,y));
            }
            if(f==1)
            {
                printf("%lld\n",ask1(x,y));
            }
            if(f==2)
            {
                modify(1,1,n,id[x],y);
            }
        }
    }
    return 0;
}

/*

*/




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值