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

浙公网安备 33010602011771号