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;
}

树上问题

技巧和思想

* 计算几何

数学

posted @ 2025-05-16 17:01  ChihiroFujisaki  阅读(10)  评论(0)    收藏  举报