AT_arc206_b [ARC206B] Slime Swap
首先对于 \(suf_i>pre_{i-1}\),那么 \([1,i),[i,n]\) 独立。其中 \(suf\) 是后缀最小值,\(pre\) 是前缀最大值。
那么可以分出很多段,现在要考虑的就是段内怎么操作使其能够排序。
合法的条件当且仅当不存在 \(i<j,col_i=col_j,p_i>p_j\),这样 \(i\) 无法交换到 \(j\) 后面。对于同色的肯定要保留最多个不更改颜色尽量使总代价最小。
一开始是考虑单调队列维护后缀中 \(p\) 升序的极长同色子序列,然后 \(i\) 向单调队列里的点连边,就能转化成二分图最大独立集,但是复杂度没法优化。
考虑本质,对同种颜色考虑,相当于选出最长的 \(p\) 升序子序列。dp 求 lis 即可。
我去,刚刚发现分段是没必要的,不过不重要没啥影响。
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
using namespace std;
using namespace __gnu_pbds;
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
#define intz(x,y) memset((x),(y),sizeof((x)))
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define tup(x) array<int,(x)>
inline ll read(){
ll x=0,f=1;char ch=nc();
while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
return x*f;
}
//void write(int x){cout<<x<<' ';}
//void write(pii x){cout<<"P("<<x.fi<<','<<x.se<<")\n";}
//void write(vector<auto>x){for(auto i:x)write(i);cout<<'\n';}
//void write(auto *a,int l,int r){for(int i=l;i<=r;i++)write(a[i]);cout<<'\n';}
inline ll lowbit(ll x){return x&-x;}
#define pcount(x) __builtin_popcount(x)
inline void cmx(ll &x,ll y){if(y>x)x=y;}
inline void cmn(ll &x,ll y){if(y<x)x=y;}
const int mod=998244353;
ll qp(ll x,int y){ll res=1;for(;y;x=x*x%mod,y>>=1)if(y&1)res=res*x%mod;return res;}
const int N=2e5+5;
#define int ll
int p[N],c[N],suf[N],pre[N];vector<int>d[N];
inline void UesugiErii(){
int n;cin>>n;suf[n+1]=1e9;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=n;i;i--)suf[i]=min(suf[i+1],p[i]);
for(int i=1;i<=n;i++)pre[i]=max(pre[i-1],p[i]);
int lst=1,ans=0;
for(int i=2;i<=n+1;i++)
if(suf[i]>pre[i-1]||i==n+1){
for(int j=lst;j<i;j++){
ans+=c[j];
if(!d[c[j]].size()||d[c[j]].back()<p[j]){d[c[j]].pb(p[j]);continue;}
int it=lower_bound(d[c[j]].begin(),d[c[j]].end(),p[j])-d[c[j]].begin();d[c[j]][it]=p[j];
}
for(int j=lst;j<i;j++)
ans-=d[c[j]].size()*c[j],d[c[j]].clear();
lst=i;
}
cout<<ans;
}
signed main(){
//IO();//cfast;
int _=1;//cin>>_;
for(;_;_--)UesugiErii();
return 0;
}

浙公网安备 33010602011771号