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 }
View Code

 

posted @ 2017-10-24 19:58  Blue233333  阅读(125)  评论(0编辑  收藏  举报