LGP7219题解

奇怪做法来分享一下。

首先这个位置关系很容易就让人想到笛卡尔树啊,考虑在笛卡尔树上面 DP。然后你发现根本就不会设状态。

但是我们发现一件事情,笛卡尔树上的每一个节点都代表一个可能成为星座的二维区间。

并且容易发现,每颗星星都被包含在一条从祖先到孙子的链中。

题意相当于让我们求每个节点上只能有最多一颗星星且选择星星权值最大的方案数。

相当于给定若干条自上而下的链,需要选择若干条满足链互不相交且权值和最大,现在可以设 DP 状态了。

\(dp[u]\) 表示所有选取的链都在 \(u\) 子树中的最大权值。如果不选显然是 \(dp[u]=dp[L[u]]+dp[R[u]]\)

如果选择的话,需要加上这条链上挂着的子树的权值之和,不难发现这些子树都是链上节点的兄弟。

于是设 \(g[u]\) 为自己兄弟节点的 dp 数组的值,搞个倍增就能 \(O(n\log n)\) 了。

当然也可以 dfs序+BIT 的说。

#include<cstdio>
#include<cctype>
#include<vector>
typedef long long ll;
const int M=2e5+5;
int n,m,a[M],d[M],f[M][20];ll sum,dp[M],g[M][20];int L[M],R[M];int top,stk[M];std::vector<int>son[M][20];
struct chain{
	int v,w;
};std::vector<chain>t[M];
inline ll max(const ll&a,const ll&b){
	return a>b?a:b;
}
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline void Build(){
	for(int i=1;i<=n;++i){
		if(a[i]>=a[stk[top]]){
			while(top&&a[i]>=a[stk[top]])R[stk[top-1]]=stk[top],--top;L[i]=stk[top+1];
		}
		stk[++top]=i;
	}
	while(top)R[stk[top-1]]=stk[top],--top;
}
inline void DFS(const int&u){
	for(int i=1;f[u][i-1];++i)f[u][i]=f[f[u][i-1]][i-1];d[u]=d[f[u][0]]+1;
	if(L[u])f[L[u]][0]=u,DFS(L[u]);if(R[u])f[R[u]][0]=u,DFS(R[u]);
}
inline void DP(const int&u){
	if(L[u])DP(L[u]),son[f[u][0]][1].push_back(L[u]);if(R[u])DP(R[u]),son[f[u][0]][1].push_back(R[u]);
	if(L[u]&&R[u])g[L[u]][0]=dp[R[u]],g[R[u]][0]=dp[L[u]];dp[u]=dp[L[u]]+dp[R[u]];
	for(int k=1;k<=17;++k)for(int&v:son[u][k])g[v][k]=g[v][k-1]+g[f[v][k-1]][k-1],son[f[u][k]][k+1].push_back(v);
	for(chain&E:t[u]){
		int v=E.v;ll sum(dp[L[E.v]]+dp[R[E.v]]+E.w);
		for(int k=17;~k;--k)if(d[f[v][k]]>=d[u])sum+=g[v][k],v=f[v][k];
		dp[u]=max(dp[u],sum);
	}
}
signed main(){
	n=read();for(int i=1;i<=n;++i)a[i]=read();Build();DFS(stk[1]);m=read();
	for(int i=1;i<=m;++i){
		int x,y,c,u;x=read();y=read();c=read();u=x;sum+=c;
		for(int k=17;~k;--k)if(f[u][k]&&a[f[u][k]]<y)u=f[u][k];t[u].push_back((chain){x,c});
	}
	DP(stk[1]);printf("%lld",sum-dp[stk[1]]);
}
posted @ 2022-07-14 14:42  Prean  阅读(14)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};