CF2150C题解
Forgive_Me · · 题解
赛时苦心研究 B 不会做,赛后发现 C 竟然比 B 简单?
(本题解一如既往地贯彻了我的废话精神?)
想了想发现自己不会贪心,所以必然有 dp 做法?
不难想到一个状态
这时候就可以顺利推出这个
code。然后就可以获得一发罚时的好成绩。
考虑优化,这个东西看起来就很有前途,因为发现转移就是按
此时只需要上一个维护区间最大值的线段树即可,第二种转移在主函数取一次
#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();
}