BZOJ2809: [Apio2012]dispatching

给n<=100000的树,每个点有权值和代价,有m<=1e9的容量,问:一个点权值*子树内代价总和不超过容量的最大点数的最大值。

其实就是要合并。平衡树、线段树、可并堆挑一个。

可并堆由于没法二分,故“正难取反”,维护最大的,在不够装时弹掉。

 1 #include<string.h>
 2 #include<stdlib.h>
 3 #include<stdio.h>
 4 #include<math.h>
 5 //#include<assert.h>
 6 #include<algorithm>
 7 //#include<iostream>
 8 using namespace std;
 9 
10 int n,m;
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 void insert(int x,int y) {in(x,y); in(y,x);}
15 
16 #define LL long long
17 struct leftist
18 {
19     struct Node
20     {
21         int size,ls,rs,dis,v; LL sum;
22     }a[maxn];
23     leftist() {a[0].dis=-1;}
24     int merge(int x,int y)
25     {
26         if (!x || !y) return x^y;
27         if (a[x].v<a[y].v) {int t=x; x=y; y=t;}
28         a[x].rs=merge(a[x].rs,y);
29         if (a[a[x].ls].dis<a[a[x].rs].dis) {int t=a[x].ls; a[x].ls=a[x].rs; a[x].rs=t;}
30         a[x].dis=a[a[x].rs].dis+1;
31         a[x].size=a[a[x].ls].size+a[a[x].rs].size+1;
32         a[x].sum=a[a[x].ls].sum+a[a[x].rs].sum+a[x].v;
33         return x;
34     }
35     void push(int id,int &root,int val)
36     {
37         a[id].v=val; a[id].size=1; a[id].sum=val;
38         a[id].ls=a[id].rs=a[id].dis=0;
39         root=merge(root,id);
40     }
41     void pop(int &root) {root=merge(a[root].ls,a[root].rs);}
42     int top(int root) {return a[root].v;}
43 }q;
44 int root[maxn];
45 int find(int x) {return x==root[x]?x:(root[x]=find(root[x]));}
46 
47 int b[maxn]; LL ans=-1e18;
48 void dfs(int x)
49 {
50     for (int i=first[x];i;i=edge[i].next)
51     {
52         const Edge &e=edge[i];
53         dfs(e.to);
54         root[x]=q.merge(root[x],root[e.to]);
55     }
56     while (q.a[root[x]].sum>m) q.pop(root[x]);
57     ans=max(ans,q.a[root[x]].size*1ll*b[x]);
58 }
59 
60 int main()
61 {
62     scanf("%d%d",&n,&m);
63     int rr=0;
64     for (int i=1,x,y;i<=n;i++)
65     {
66         scanf("%d%d%d",&x,&y,&b[i]);
67         if (x==0) rr=i; else in(x,i);
68         q.push(i,root[i],y);
69     }
70     dfs(rr);
71     printf("%lld\n",ans);
72     return 0;
73 }
View Code

 

posted @ 2018-01-11 09:53  Blue233333  阅读(170)  评论(0编辑  收藏  举报