CF1334F Strange Function

考虑 \(dp\) 状态,容易想到状态 \(f_{i,j}\) 表示前 \(i\)\(a\) 可以匹配前 \(j\)\(b\) 的最大权值,状态数位 \(O(n^2)\)
但我们马上发现 \(b_j\) 是唯一的,所以可以省去第二维。
考虑暴力转移:

\[f_{i} = \max_{0<k<i,a_k=b_{j-1}}{f_{k} + \sum_{t=k+1}^{i-1} [p_t>0][a_t \leq a_k]p_t} + p_i \]

这样时间复杂度为 \(\mathcal{O}(n^2)\),考虑优化。
考虑定义 \(g_{k} = f_k + \sum_{t=k+1}^{i-1} [p_t>0][a_t \leq a_k]p_t\),则每一次会使 \(a_k \geq a_i\)\(g_k\) 全部加上 \(p_i\),当前仅当 \(p_i>0\).
显然这是一个后缀加操作,于是维护树状数组,维护后缀加,单点查询和单点取 \(\max\),单点取 \(\max\) 可以拆成两个后缀加和一个单点查。

时间复杂度:\(\mathcal{O}(n \log n)\)

#include<bits/stdc++.h>
#define ll long long 

using namespace std;

const int N = 5e5+5;
const ll INF = 1e18+7;

int n,m;
int a[N];
int p[N],b[N],pos[N];
ll f[N],sum;

namespace BIT{
	ll tr[N];
	int lowbit(int x){
		return x&(-x);
	}
	ll query(ll x){
		ll res=0;
		for(;x;x-=lowbit(x))
			res+=tr[x];
		return res;
	}
	
	void add(int x,ll w){
		for(;x<=n;x+=lowbit(x))
			tr[x]+=w;
	}
}
int main() {
	cin>>n;
	
	for(int i=1;i<=n;i++)
		cin>>a[i];
	
	for(int i=1;i<=n;i++)
		cin>>p[i],sum+=p[i];
	
	cin>>m;
	for(int i=1;i<=m;i++)
		cin>>b[i],pos[b[i]]=i;
	
	BIT::add(1,-INF);
	for(int i=1;i<=n;i++){
		int t=pos[a[i]],pre=t-1;
		if(t)f[i]=BIT::query(b[pre])+p[i];
		else f[i]=-INF;
		if(p[i]>0)BIT::add(a[i],p[i]);
		ll s=BIT::query(a[i]);
		if(s<f[i]){
			BIT::add(a[i],f[i]-s);
			BIT::add(a[i]+1,s-f[i]);
		}
	}
	
	ll ans=BIT::query(b[m]);
	if(ans<-1e16)cout<<"NO";
	else cout<<"YES\n"<<sum-ans<<'\n';
	return 0;
} 
posted @ 2025-12-13 09:28  Harvey-zhuhy  阅读(3)  评论(0)    收藏  举报