BZOJ4756: [Usaco2017 Jan]Promotion Counting
n<=100000的点权树,问每个点子树内有多少个比他大。
方法一:区间第K大!……
方法二:线段树合并,值为下标,每次把所有的孩子和自己合并起来,然后线段树中直接查找即可。
1 #include<cstring> 2 #include<cstdlib> 3 #include<cstdio> 4 //#include<assert.h> 5 #include<math.h> 6 #include<algorithm> 7 //#include<iostream> 8 using namespace std; 9 10 int n; 11 #define maxn 100011 12 struct Edge{int to,next;}edge[maxn<<1];int first[maxn],le=2; 13 void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;} 14 int num[maxn],root[maxn]; 15 struct SMT 16 { 17 struct Node 18 { 19 int cnt; 20 int l,r; 21 int ls,rs; 22 Node() {ls=rs=0;} 23 }a[maxn*20]; 24 //值经过离散化成1~n 25 int size; 26 SMT() {size=0;} 27 void up(int x) 28 { 29 const int &p=a[x].ls,&q=a[x].rs; 30 a[x].cnt=a[p].cnt+a[q].cnt; 31 } 32 void build(int &x,int L,int R,int pos) 33 { 34 x=++size; 35 a[x].l=L;a[x].r=R; 36 if (a[x].l==a[x].r) 37 { 38 a[x].cnt=1; 39 a[x].ls=a[x].rs=0; 40 } 41 else 42 { 43 const int mid=(L+R)>>1; 44 if (pos<=mid) build(a[x].ls,L,mid,pos),a[x].rs=0; 45 else build(a[x].rs,mid+1,R,pos),a[x].ls=0; 46 up(x); 47 } 48 } 49 void build(int &x,int pos) {build(x,1,n,pos);} 50 int query(int x,int k) 51 { 52 if (a[x].r<=k) return 0; 53 if (a[x].l>k) return a[x].cnt; 54 return query(a[x].ls,k)+query(a[x].rs,k); 55 } 56 int combine(int x,int y) 57 { 58 if (!x || !y) return x+y; 59 a[x].ls=combine(a[x].ls,a[y].ls); 60 a[x].rs=combine(a[x].rs,a[y].rs); 61 up(x); 62 return x; 63 } 64 }t; 65 bool isdigit(char c) {return c>='0' && c<='9';} 66 int qread() 67 { 68 char c;int s=0;while (!isdigit(c=getchar())); 69 do s=s*10+c-'0'; while (isdigit(c=getchar()));return s; 70 } 71 int lisan[maxn]; 72 int ans[maxn]; 73 void dfs(int x) 74 { 75 t.build(root[x],num[x]); 76 for (int i=first[x];i;i=edge[i].next) 77 { 78 const Edge &e=edge[i]; 79 dfs(e.to); 80 root[x]=t.combine(root[x],root[e.to]); 81 } 82 ans[x]=t.query(root[x],num[x]); 83 } 84 int main() 85 { 86 n=qread(); 87 for (int i=1;i<=n;i++) lisan[i]=num[i]=qread(); 88 sort(lisan+1,lisan+1+n); 89 for (int i=1;i<=n;i++) num[i]=lower_bound(lisan+1,lisan+1+n,num[i])-lisan; 90 for (int i=2,x;i<=n;i++) x=qread(),in(x,i); 91 dfs(1); 92 for (int i=1;i<=n;i++) printf("%d\n",ans[i]); 93 return 0; 94 }