BZOJ[4756][Usaco2017 Jan]Promotion Counting 线段树合并
2017-12-09 15:37
441 查看
题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=4756
裸的线段树合并
对于每个点建一个权值线段树
这里采用了动态开点,常数较大(线段树范围是1~MAXN),但是省略了离散化
代码如下:
裸的线段树合并
对于每个点建一个权值线段树
这里采用了动态开点,常数较大(线段树范围是1~MAXN),但是省略了离散化
代码如下:
#include<ctype.h> #include<cstdio> #define N 100050 using namespace std; const int INF=1000000000;///数最大这么多 inline int read(){ int x=0,f=1;char c; do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f; } int top,n,x; int ans ,fir ,a ; struct Edge{ int to,nex; Edge(int _=0,int __=0):to(_),nex(__){} }nex ; struct Node{ int sum,l,r; Node *ls,*rs; inline void maintain() { sum=ls->sum+rs->sum; } Node(int,int); }*root ,*null;///定义一个null,可以省略好多问题(同平衡树那个) Node::Node(int _=0,int __=0):l(_),r(__){ sum=0; ls=rs=null; } inline void add(int x,int y){ nex[++top]=Edge(y,fir[x]); fir[x]=top; } void Add(int x,Node *&k,int L,int R){///L,R记录左右节点(动态开点用的) if(k==null) k=new Node(L,R);///动态开点,如果原先没有这个点就加上 if(k->l==k->r){ k->sum++; return; } int mid=L+R>>1; if(x<=mid) Add(x,k->ls,L,mid); else Add(x,k->rs,mid+1,R); k->maintain(); } int Query(int l,int r,Node *k){ if(k==null) return 0; if(k->l>=l && k->r<=r){ return k->sum; } int mid=k->l+k->r>>1,t; if(mid>=r) t=Query(l,r,k->ls); else if(mid<l) t=Query(l,r,k->rs); else t=Query(l,r,k->ls)+Query(l,r,k->rs); k->maintain(); return t; } void Merge(Node *&x,Node *&y){ if(y==null) return; if(x==null){ x=y; return; } x->sum+=y->sum; Merge(x->ls,y->ls);Merge(x->rs,y->rs); } void Debug(Node *x){///调试orz.. if(x->ls!=null) Debug(x->ls); if(x->rs!=null) Debug(x->rs); printf("%d %d %d\n",x->l,x->r,x->sum); } void dfs(int x){ for(int i=fir[x];i;i=nex[i].nex){ dfs(nex[i].to); Merge(root[x],root[nex[i].to]);///求出子树答案后,合并到本节点上 } ans[x]=Query(a[x]+1,INF,root[x]); } int main(){ null=new Node(-1,-1); null->ls=null->rs=null; null->sum=0; n=read(); for(int i=1;i<=n;i++) a[i]=read(),root[i]=null; for(int i=2;i<=n;i++){ x=read(); add(x,i); } for(int i=1;i<=n;i++) Add(a[i],root[i],1,INF); dfs(1); for(int i=1;i<=n;i++){ printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- bzoj 4756: [Usaco2017 Jan]Promotion Counting (线段树合并)
- bzoj4756: [Usaco2017 Jan]Promotion Counting 线段树合并
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting 线段树合并
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting(线段树合并)
- [BZOJ4756] [Usaco2017 Jan]Promotion Counting(线段树合并)
- 4756: [Usaco2017 Jan]Promotion Counting 线段树合并
- [BZOJ4756][Usaco2017 Jan]Promotion Counting(可持久化线段树)
- bzoj 4756: [Usaco2017 Jan]Promotion Counting
- 【bzoj4756】[Usaco2017 Jan]Promotion Counting
- [BZOJ4756][Usaco2017 Jan]Promotion Counting 树状数组
- 【bzoj 4756】[Usaco2017 Jan] Promotion Counting
- 【bzoj4756】[Usaco2017 Jan]Promotion Counting 离散化+树状数组
- 【bzoj 4756】Promotion Counting(线段树合并)
- 【bzoj4756】[Usaco2017 Jan]Promotion Counting
- BZOJ4756: [Usaco2017 Jan]Promotion Counting
- bzoj 4756: [Usaco2017 Jan]Promotion Counting【dfs+树状数组】
- BZOJ_4756_[Usaco2017 Jan]Promotion Counting_树状数组
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting dfs序+主席树
- [Usaco2017 Jan]Promotion Counting 线段树合并模板/dfs序
- BZOJ 4756 线段树合并(线段树)