bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS
4919: [Lydsy1706月赛]大根堆
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 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
3 0
1 1
2 1
3 1
4 1
5 1
Sample Output
5
HINT
Source
题解:
因为要维护一个大顶堆,所以就等价于维护每条链都是一个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 }