【BZOJ】4756: [Usaco2017 Jan]Promotion Counting
【题意】带点权树,统计每个结点子树内点权比它大的结点数。
【算法】线段树合并
【题解】对每个点建权值线段树(动态开点),DFS中将自身和儿子线段树合并后统计。
注意三个量tot,cnt,tots,细心查错。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=200010; int n,first[maxn],cnt,tot,tots,root[maxn],a[maxn],b[maxn],ans[maxn]; struct edge{int v,from;}e[maxn*2]; void ins(int u,int v){tots++;e[tots].v=v;e[tots].from=first[u];first[u]=tots;} struct cyc{int l,r,sum;}t[maxn*10]; void insert(int l,int r,int &x,int y){ if(!x)x=++cnt;t[x].sum++; if(l==r)return;// int mid=(l+r)>>1; if(y<=mid)insert(l,mid,t[x].l,y); else insert(mid+1,r,t[x].r,y); } int merge(int x,int y){ if(!x||!y)return x^y;//1 t[x].l=merge(t[x].l,t[y].l); t[x].r=merge(t[x].r,t[y].r);//2 t[x].sum=t[t[x].l].sum+t[t[x].r].sum;//3 return x; } int ask(int left,int right,int k,int l,int r){ if(l<=left&&right<=r)return t[k].sum; else{ int mid=(left+right)>>1,sum=0; if(l<=mid)sum=ask(left,mid,t[k].l,l,r); if(r>mid)sum+=ask(mid+1,right,t[k].r,l,r); return sum; } } void dfs(int x){ insert(1,tot,root[x],a[x]); for(int i=first[x];i;i=e[i].from){ dfs(e[i].v); root[x]=merge(root[x],root[e[i].v]); } if(a[x]<tot)ans[x]=ask(1,tot,root[x],a[x]+1,tot); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; } for(int i=2;i<=n;i++){ int fa;scanf("%d",&fa); ins(fa,i); } sort(b+1,b+n+1);tot=n; tot=unique(b+1,b+tot+1)-b-1; for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+tot+1,a[i])-b; dfs(1); for(int i=1;i<=n;i++)printf("%d\n",ans[i]); return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· ASP.NET Core - 日志记录系统(二)
· 在外漂泊的这几年总结和感悟,展望未来
· 博客园 & 1Panel 联合终身会员上线
· 支付宝事故这事儿,凭什么又是程序员背锅?有没有可能是这样的...
· https证书一键自动续期,帮你解放90天限制
· 在 ASP.NET Core WebAPI如何实现版本控制?