[Feyat Cup 1.0][JZOJ3338]法法塔的奖励
来源:互联网 发布:神人鉴知 编辑:程序博客网 时间:2024/06/05 21:07
题目大意
给定一棵
对于以
求以每一个节点为根的子树的答案。
题目分析
显然我们需要递归处理子树,合并所有儿子子树的信息,更新当前子树答案。
考虑使用什么数据结构维护最长不下降子序列,我们可以用权值线段树、平衡树等等。
然后合并所有儿子上的数据结构,更新答案即可。
我使用的是权值线段树,合并时直接合并即可。至于线段树合并为什么是
具体细节见代码实现。
代码实现
#include <iostream>#include <cstdio>#include <cctype>using namespace std;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); } while (isdigit(ch)) { x=x*10+ch-'0'; ch=getchar(); } return x*f;}int buf[20];void write(int x){ if (x<0) putchar('-'),x=-x; buf[0]=0; while (x) { buf[++buf[0]]=x%10; x/=10; } if (!buf[0]) buf[++buf[0]]=0; while (buf[0]) putchar(buf[buf[0]--]+'0');}const int N=100050;const int L=100000;const int S=N*20;struct segment_tree{ int v[S],son[S][2],root[N]; int tot; int merge(int rt1,int rt2,int l,int r) { if (!(1ll*rt1*rt2)) return rt1+rt2; v[rt1]=max(v[rt1],v[rt2]); if (l==r) return rt1; int mid=l+r>>1; son[rt1][0]=merge(son[rt1][0],son[rt2][0],l,mid); son[rt1][1]=merge(son[rt1][1],son[rt2][1],mid+1,r); return rt1; } int query(int rt,int st,int en,int l,int r) { if (!rt) return 0; if (l==st&&r==en) return v[rt]; int mid=l+r>>1; if (en<=mid) return query(son[rt][0],st,en,l,mid); else if (mid+1<=st) return query(son[rt][1],st,en,mid+1,r); else return max(query(son[rt][0],st,mid,l,mid),query(son[rt][1],mid+1,en,mid+1,r)); } int change(int rt,int y,int l,int r,int edit) { if (!rt) rt=++tot; if (l==r) { v[rt]=max(edit,v[rt]); return rt; } int mid=l+r>>1; if (y<=mid) son[rt][0]=change(son[rt][0],y,l,mid,edit); else son[rt][1]=change(son[rt][1],y,mid+1,r,edit); v[rt]=max(v[son[rt][0]],v[son[rt][1]]); return rt; }}t;int ans[N],fa[N],last[N],next[N],tov[N],val[N];int tot,n;void insert(int x,int y){ tov[++tot]=y; next[tot]=last[x]; last[x]=tot;}void dfs(int x){ int i=last[x],y,rt=0; while (i) { y=tov[i]; dfs(y); rt=t.merge(rt,t.root[y],1,L); i=next[i]; } ans[x]=t.query(rt,1,val[x],1,L)+1; t.root[x]=t.change(rt,val[x],1,L,ans[x]);}int main(){ freopen("reward.in","r",stdin); freopen("reward.out","w",stdout); n=read(); read(); for (int i=2;i<=n;i++) fa[i]=read(),insert(fa[i],i); for (int i=1;i<=n;i++) val[i]=read(); dfs(1); for (int i=1;i<=n;i++) write(ans[i]),putchar(i!=n?' ':'\n'); fclose(stdin); fclose(stdout); return 0;}
0 0
- [Feyat Cup 1.0][JZOJ3338]法法塔的奖励
- 3145: [Feyat cup 1.5]Str
- 法法塔的奖励
- 最高的奖励
- 最高的奖励 【贪心】
- 1163 最高的奖励
- 最高的奖励
- 1123: 最高的奖励
- 最近获得的奖励
- 1163 . 最高的奖励
- 1163 最高的奖励
- 最高的奖励
- 最高的奖励
- 最高的奖励
- 最高的奖励
- 最高的奖励
- 最高的奖励
- 奖励
- App架构经验总结
- 天呐,坑爹的xcode
- 受限玻尔兹曼机准备知识——蒙特卡洛方法
- JavaScript学习笔记——引用类型:Array类型
- python编程书推荐9本免费的
- [Feyat Cup 1.0][JZOJ3338]法法塔的奖励
- 求链表结点的阶乘和
- 小备注
- Python初见 List,Tuple,Dict,Set的增删改查
- c语言中!&&||的逻辑小结
- url-pattern值格式
- 计算机网络体系结构—数据传递流
- Linux 4.33 字符设备驱动分析
- Windows 7(64位)搭建Python开发环境