bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS

4919: [Lydsy1706月赛]大根堆

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 599  Solved: 260
[Submit][Status][Discuss]

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

Sample Output

5

HINT

 

Source

本OJ付费获得

题解:

   因为要维护一个大顶堆,所以就等价于维护每条链都是一个lis的过程,然后合并可以直接用set启发式合并,

   并且模拟LIS过程。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 #include<vector>
 7 #include<set>
 8 #include<map>
 9 
10 #define zz multiset<int>::iterator 
11 #define ll long long
12 #define inf 1000000007
13 #define N 200007
14 
15 #define Wb putchar(' ')
16 #define We putchar('\n')
17 #define rg register int
18 #define fo(i,x,y) for (rg i=x;i<=y;i++)
19 #define fd(i,x,y) for (rg i=y;i>=x;i--)
20 #define fb(i,x) for (rg i=x;~i;i=nxt[i])
21 #define fz(i,x,y) for (zz i=x;i!=y;i++)
22 #define fi first
23 #define se second
24 #define pb(x) push_back(x)
25 #define SZ(x) ((int)x.size()) 
26 using namespace std;
27 inline int read()
28 {
29     int x=0,f=1;char ch=getchar();
30     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
31     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
32     return x*f;
33 }
34 inline void write(ll x)
35 {
36     if(x<0) putchar('-'),x=-x;
37     if (x==0) putchar(48);
38     int num=0;char c[20];
39     while(x) c[++num]=(x%10)+48,x/=10;
40     while(num) putchar(c[num--]);
41 }
42 
43 int n,m;
44 int a[N];
45 int cnt,hed[N],rea[N],nxt[N];
46 multiset<int>s[N];
47 
48 void add(int u,int v)
49 {
50     nxt[++cnt]=hed[u];
51     hed[u]=cnt;
52     rea[cnt]=v;
53 }
54 void merge(int x,int y)
55 {
56     if (SZ(s[x])>SZ(s[y])) swap(s[x],s[y]);
57     fz(z,s[x].begin(),s[x].end())
58         s[y].insert(*z);
59     s[x].clear();
60 }
61 void dfs(int u)
62 {
63     fb(i,hed[u])
64     {
65         rg v=rea[i];
66         dfs(v),merge(v,u);
67     }
68     zz z=s[u].lower_bound(a[u]);
69     if (z!=s[u].end()) s[u].erase(z);
70     s[u].insert(a[u]);
71 }
72 int main()
73 {
74     memset(hed,-1,sizeof(hed));
75     n=read();
76     fo(i,1,n)
77     {
78         rg x;
79         a[i]=read(),x=read();
80         if (x) add(x,i);
81     }
82     dfs(1);
83     write(s[1].size());
84 }

猜你喜欢

转载自www.cnblogs.com/fengzhiyuan/p/8983633.html