您的位置:首页 > 其它

BZOJ4756: [Usaco2017 Jan]Promotion Counting

2017-10-24 19:58 447 查看

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

.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 [p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: