专栏文章
CF2150C题解
CF2150C题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @minrk7g0
- 此快照首次捕获于
- 2025/12/02 07:11 3 个月前
- 此快照最后确认于
- 2025/12/02 07:11 3 个月前
赛时苦心研究 B 不会做,赛后发现 C 竟然比 B 简单?
(本题解一如既往地贯彻了我的废话精神?)
想了想发现自己不会贪心,所以必然有 dp 做法?
不难想到一个状态 表示 当前决策第 个物品, 已经选了前 个物品时的最大价值。
考虑你当前这个物品 , 如果能选,说明 的前 个中没有 。形式化的可以记一个 表示 的第 个在 中的位置,这个限制就转化为了 。
乍一看这个 dp 应该是 的,因为我们每一次都要考虑 的转移点,但真的是这样吗?
回头看一下前面推的限制,这个 的作用只用于约束 是否能选,仅此而已。所以我们从 能到达的有用状态只有 和 。
考虑你当前这个物品 , 如果能选,说明 的前 个中没有 。形式化的可以记一个 表示 的第 个在 中的位置,这个限制就转化为了 。
乍一看这个 dp 应该是 的,因为我们每一次都要考虑 的转移点,但真的是这样吗?
回头看一下前面推的限制,这个 的作用只用于约束 是否能选,仅此而已。所以我们从 能到达的有用状态只有 和 。
这时候就可以顺利推出这个 的 dp 转移了,特别注意每一个东西至少要被其中一个人选:
code。然后就可以获得一发罚时的好成绩。
考虑优化,这个东西看起来就很有前途,因为发现转移就是按 的大小分成两部分,第一维又可以滚掉,就和这个很像。
此时只需要上一个维护区间最大值的线段树即可,第二种转移在主函数取一次 。
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=200010;
int w[N],a[N],b[N],c[N],pos[N];
struct node{
int l,r,data,lazy;
}p[4*N];
void build(int pos,int l,int r){
p[pos].l=l,p[pos].r=r,p[pos].lazy=0,p[pos].data=0;
if(l==r) return ;
int mid=(l+r)/2;
build(pos*2,l,mid);build(pos*2+1,mid+1,r);
}
void pd(int pos){
int v=p[pos].lazy;p[pos].lazy=0;
p[pos*2].data+=v,p[pos*2+1].data+=v;
p[pos*2].lazy+=v,p[pos*2+1].lazy+=v;
}
void update(int pos,int l,int r,int v){
if(p[pos].l==l&&p[pos].r==r){
p[pos].lazy+=v;
p[pos].data+=v;
return ;
}
if(p[pos].lazy) pd(pos);
int mid=(p[pos].l+p[pos].r)/2;
if(l<=mid) update(pos*2,l,min(r,mid),v);
if(r>mid) update(pos*2+1,max(mid+1,l),r,v);
p[pos].data=max(p[pos*2].data,p[pos*2+1].data);
}
int query(int pos,int l,int r){
if(p[pos].l==l&&p[pos].r==r) return p[pos].data;
if(p[pos].lazy) pd(pos);
int mid=(p[pos].l+p[pos].r)/2,ans=-1e14;
if(l<=mid) ans=max(ans,query(pos*2,l,min(r,mid)));
if(r>mid) ans=max(ans,query(pos*2+1,max(mid+1,l),r));
return ans;
}
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i],c[b[i]]=i;
for(int i=1;i<=n;i++) pos[i]=c[a[i]];
build(1,0,n);
for(int i=1;i<=n;i++){
int now=query(1,0,pos[i]-1),res=query(1,pos[i],pos[i]);
if(res<now) update(1,pos[i],pos[i],now-res);
update(1,0,pos[i]-1,w[a[i]]);
//if(pos[i]>j) f[i][j]=max(f[i][j],f[i-1][j]+w[a[i]]);
//f[i][max(j,pos[i])]=max(f[i][max(j,pos[i])],f[i-1][j]);
}
int ans=query(1,0,n);
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;while(T--) solve();
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...