bzoj4919 [Lydsy1706月赛]大根堆
Description
给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点。每个点有一个权值v_i。
你需要将这棵树转化成一个大根堆。确切地说,你需要选择尽可能多的节点,满足大根堆的性质:对于任意两个点i,j,如果i在树上是j的祖先,那么v_i>v_j。
请计算可选的最多的点数,注意这些点不必形成这棵树的一个连通子树。
Input
第一行包含一个正整数n(1<=n<=200000),表示节点的个数。
接下来n行,每行两个整数v_i,p_i(0<=v_i<=10^9,1<=p_i<i,p_1=0),表示每个节点的权值与父亲。
Output
输出一行一个正整数,即最多的点数。
Sample Input
6
3 0
1 1
2 1
3 1
4 1
5 1
3 0
1 1
2 1
3 1
4 1
5 1
Sample Output
5
设f[i][j]表示i的子树内选择点集的权值最大值为j时最多选几个点,用启发式合并配合线段树转移即可。
时间复杂度O(nlog2n)。
观察转移可以得到如下等效的简单做法:当树退化成链时,其实就是求LIS一般情况下,对于每个点维护一个集合,每次将x点所有儿子的集合合并,然后用v去替换里面最小的比它大的数,最后根节点的集合大小就是答案。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[400001]; 11 int num,head[200001],c[20000001],ch[20000001][2],flag,pos,root[200001],n,a[200001],b[200001]; 12 void add(int u,int v) 13 { 14 num++; 15 edge[num].next=head[u]; 16 head[u]=num; 17 edge[num].to=v; 18 } 19 void pushup(int rt) 20 { 21 c[rt]=c[ch[rt][0]]+c[ch[rt][1]]; 22 } 23 int merge(int a,int b) 24 { 25 if (!a) return b; 26 if (!b) return a; 27 ch[a][0]=merge(ch[a][0],ch[b][0]); 28 ch[a][1]=merge(ch[a][1],ch[b][1]); 29 c[a]+=c[b]; 30 c[b]=0; 31 return a; 32 } 33 void del(int rt,int l,int r) 34 { 35 if (l==r) 36 { 37 c[rt]--; 38 flag=0; 39 return; 40 } 41 int mid=(l+r)/2; 42 if (c[ch[rt][0]]) del(ch[rt][0],l,mid); 43 else del(ch[rt][1],mid+1,r); 44 pushup(rt); 45 } 46 void update(int &rt,int l,int r,int x) 47 { 48 if (!rt) rt=++pos; 49 if (l==r) 50 { 51 if (c[rt]==0) c[rt]++,flag=1; 52 return; 53 } 54 int mid=(l+r)/2; 55 if (x<=mid) 56 { 57 update(ch[rt][0],l,mid,x); 58 if (flag&&c[ch[rt][1]]) del(ch[rt][1],mid+1,r); 59 } 60 else 61 update(ch[rt][1],mid+1,r,x); 62 pushup(rt); 63 } 64 void dfs(int x) 65 {int i; 66 for (i=head[x];i;i=edge[i].next) 67 { 68 int v=edge[i].to; 69 dfs(v); 70 root[x]=merge(root[x],root[v]); 71 } 72 flag=0; 73 update(root[x],1,n,a[x]); 74 } 75 int main() 76 {int i,pa,sz; 77 cin>>n; 78 for (i=1;i<=n;i++) 79 { 80 scanf("%d",&a[i]); 81 b[i]=a[i]; 82 scanf("%d",&pa); 83 if (pa) 84 add(pa,i); 85 } 86 sort(b+1,b+n+1); 87 sz=unique(b+1,b+n+1)-b-1; 88 for (i=1;i<=n;i++) 89 a[i]=lower_bound(b+1,b+sz+1,a[i])-b; 90 dfs(1); 91 cout<<c[root[1]]; 92 } 93