BZOJ2809 dispatching 【可并堆】

题目分析:

yy一下就知道了,合并用可并堆少个log。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 const int maxn = 102000;
 5  
 6 int n,m;
 7 int b[maxn],c[maxn],l[maxn],sz[maxn];
 8 long long tot[maxn];
 9 int dis[maxn],val[maxn],ch[maxn][2],pts[maxn];
10 vector <int> g[maxn];
11 long long ans = 0;
12  
13 int merge(int r1,int r2){
14     if(r1 == 0) return r2; if(r2 == 0) return r1;
15     if(val[r1] > val[r2]){
16     ch[r1][1] = merge(ch[r1][1],r2);
17     if(dis[ch[r1][0]] < dis[ch[r1][1]]) swap(ch[r1][0],ch[r1][1]);
18     if(ch[r1][1]) dis[r1] = dis[ch[r1][1]] + 1;
19     else dis[r1] = 0;
20     return r1;
21     }else{
22     ch[r2][1] = merge(r1,ch[r2][1]);
23     if(dis[ch[r2][0]] < dis[ch[r2][1]]) swap(ch[r2][0],ch[r2][1]);
24     if(ch[r2][1]) dis[r2] = dis[ch[r2][1]] + 1;
25     else dis[r2] = 0;
26     return r2;
27     }
28 }
29  
30 void read(){
31     scanf("%d%d",&n,&m);
32     for(int i=1;i<=n;i++) scanf("%d%d%d",&b[i],&c[i],&l[i]);
33     for(int i=1;i<=n;i++){g[b[i]].push_back(i);}
34 }
35  
36 void dfs(int now){
37     for(int i=0;i<g[now].size();i++){
38     dfs(g[now][i]);
39     sz[now] += sz[g[now][i]];
40     tot[now] += tot[g[now][i]];
41     }
42     sz[now]++; tot[now] += c[now];
43     for(int i=0;i<g[now].size();i++)pts[now]=merge(pts[now],pts[g[now][i]]);
44     while(tot[now] > m){
45     tot[now] -= val[pts[now]];sz[now]--;
46     pts[now] = merge(ch[pts[now]][0],ch[pts[now]][1]);
47     }
48     ans = max(ans,1ll*l[now]*sz[now]);
49 }
50  
51 void work(){
52     for(int i=1;i<=n;i++) pts[i] = i,val[i] = c[i];
53     dfs(g[0][0]);
54     printf("%lld",ans);
55 }
56  
57 int main(){
58     read();
59     work();
60     return 0;
61 }

 

转载于:https://www.cnblogs.com/Menhera/p/9558209.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值