社区讨论

本人萌新刚学OI树剖写炸求dalao指教

P3252[JLOI2012] 树参与者 10已保存回复 14

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
14 条
当前快照
1 份
快照标识符
@mi6v8l3z
此快照首次捕获于
2025/11/20 11:22
4 个月前
此快照最后确认于
2025/11/20 14:45
4 个月前
查看原帖
rt,QAQ
CPP
#include <bits/stdc++.h>
#define pushup(o) sum[o]=sum[o<<1]+sum[o<<1|1]
using namespace std;
int n,s,anss=0;
struct edge
{
    int next,to;
}e[200010];
int a[100010],head[100010],sum[400040];
int fa[100010],top[100010],in[100010],seg[100010];
int siz[100010],son[100010],dep[100010],cnt;
void add(int u,int v)
{
    cnt++;
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt;
}
void dfs1(int u)
{
    siz[u]=1;
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa[u])
        {
            continue;
        }
        dep[v]=dep[u]+1;
        fa[v]=u;
        dfs1(v);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
        {
            son[u]=v;
        }
    }
}
void dfs2(int u,int tp)
{
    cnt++;
    in[u]=cnt;
    seg[cnt]=u;
    top[u]=tp;
    if(son[u])
    {
        dfs2(son[u],tp);
    }
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa[u]||v==son[u])
        {
            continue;
        }
        dfs2(v,v);
    }
}
void build(int o,int lf,int rg)
{
    if(lf==rg)
    {
        sum[o]=a[seg[lf]];
        return ;
    }
    int mid=(lf+rg)>>1;
    build(o<<1,lf,mid);
    build(o<<1|1,mid+1,rg);
    pushup(o);
}
int query(int o,int lf,int rg,int l,int r)
{
    if(l<=lf&&rg<=r)
    {
        return sum[o];
    }
    int mid=(lf+rg)>>1;
    int ans=0;
    if(l<=mid)
    {
        ans+=query(o<<1,lf,mid,l,r);
    }
    if(mid<r)
    {
        ans+=query(o<<1|1,mid+1,rg,l,r);
    }
    return ans;
}
void dfs(int u)
{
    int ans=0;
    bool vis=0;
    while(ans<s)
    {
    	if(u==1)
    	{
    		if(ans+a[1]==s)
    		{
    			anss++;
    		}
    		return ;
    	}
        int k=query(1,1,n,in[top[u]],in[u]);
        if(ans+k>s)
        {
            int ks=u;
            while(ans+query(1,1,n,in[ks],in[u])<s)
            {
                if(ks==1)
                {
                    return ;
                }
                if(dep[fa[ks]]>=dep[ks])
                {
                	return ;
                }
                ks=fa[ks];
            }
            if(ans+query(1,1,n,in[ks],in[u])==s)
            {
                anss++;
                return ;
            }  
        }
        else if(ans+k==s)
        {
            anss++;
            return ;
        }
        else if(u!=1)
        {
            ans+=k;
            u=fa[top[u]];
            continue;
        }
        return ;
    }
}
int main()
{
    cin>>n>>s;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    cnt=0;
    fa[1]=1;
    dep[1]=1;
    top[1]=1;
    dfs1(1);
    dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
        dfs(i);//每个点往上找
    }
    cout<<anss;
}

回复

14 条回复,欢迎继续交流。

正在加载回复...