YBTOJ
过过省选算法。
动态规划
字符串
图论
数据结构
左偏树
A P1552 [APIO2012] 派遣
感觉很幽默。
首先考虑在某一个点上都挂一个大根堆,然后考虑每次删除最大的 \(c_i\),之后求大根堆大小乘上 \(l_i\) 就好了。
不过这复杂度太高了,所以用左偏树维护大根堆。
#include <bits/stdc++.h>
using ll = long long;
using namespace std;
const int N=2e5+10;
int n,m,f[N],c[N],l[N],rt[N];
ll ans;
vector<int>g[N];
struct LfT{
ll tot,val[N],ls[N],rs[N],dis[N],siz[N],sum[N];
inline int pu(int x){
if(x==0)return 0;
sum[x]=sum[ls[x]]+sum[rs[x]]+val[x];
siz[x]=siz[ls[x]]+siz[rs[x]]+1;
return x;
}
int mer(int x,int y){
if(!x||!y)return pu(x)+pu(y);
if(val[x]<val[y])swap(x,y);
rs[x]=mer(rs[x],y);
if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
dis[x]=dis[rs[x]]+1;
return pu(x);
}
inline void del(int &x){ return x=mer(ls[x],rs[x]),void(); }
}t;
void dfs(int u,int fat){
for(int v:g[u])if(v^fat)dfs(v,u),rt[u]=t.mer(rt[u],rt[v]);
for(;t.sum[rt[u]]>m&&t.siz[rt[u]]>1;)t.del(rt[u]);
ans=max(ans,1ll*l[u]*t.siz[rt[u]]);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0),cin>>n>>m;
for(int i=1;i<=n;++i)cin>>f[i]>>c[i]>>l[i],g[f[i]].emplace_back(i),rt[i]=i,t.val[i]=c[i],t.pu(i);
return dfs(0,0),cout<<ans<<"\n",0;
}

浙公网安备 33010602011771号