题解:P9732 [CEOI 2023] Trade
Lucyna_Kushinada · · 题解
P9732 [CEOI 2023] Trade
简要题意
有长度为
请选定一个区间
请你最大化
题解
知识点:决策单调性,主席树,双指针。
一个显然的事实,所选定的
设当前考虑到右端点为
答案是显然的,
l' 一定单调不减,倘若l' 在r 变大之后突然变小,则说明l' 的新位置的s_i 会被选入前k 大,否则只会产生-c_i 的负贡献,既然如此,为什么不在r 没增大的时候到这个位置呢?毕竟随着区间左右扩大,前k 大是单调不减的。故得证。
所以这题满足决策单调性,且满足四边形不等式。
那第一问就是个分治处理决策单调性的板子了,用主席树可以做到时间复杂度
显然,
一个显然的思路是,在转移的过程中处理出所有最有区间,遍历每个区间,标记该区间中
但是最优区间最坏情况下有
先考虑两个最优区间
这时候
处理出
所以对于两个相邻且满足
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()
#define N 252507
#define int long long
int n,m,c[N],s[N],rt[N],pre[N];
int L=1,R=0,ans=-1e18;
struct hjt{
#define mid ((l+r)>>1)
int cnt=0;
struct node{
int ls,rs,s,c;
}tr[N*32];
inline void ins(int pre,int &k,int l,int r,int d){
k=++cnt;
tr[k]=tr[pre];
tr[k].c++;
tr[k].s+=d;
if(l==r){
return;
}
if(d<=mid){
ins(tr[pre].ls,tr[k].ls,l,mid,d);
}
else{
ins(tr[pre].rs,tr[k].rs,mid+1,r,d);
}
}
inline int ask(int x,int y,int l,int r,int d){
if(l==r){
return min(d,tr[y].c-tr[x].c)*l;
}
int cc=tr[tr[y].rs].c-tr[tr[x].rs].c;
int ss=tr[tr[y].rs].s-tr[tr[x].rs].s;
if(cc<d){
return ask(tr[x].ls,tr[y].ls,l,mid,d-cc)+ss;
}
return ask(tr[x].rs,tr[y].rs,mid+1,r,d);
}
inline int qry(int x,int y,int l,int r,int d){
if(l==r){
return l;
}
int cc=tr[tr[y].rs].c-tr[tr[x].rs].c;
if(cc<d){
return qry(tr[x].ls,tr[y].ls,l,mid,d-cc);
}
return qry(tr[x].rs,tr[y].rs,mid+1,r,d);
}
#undef mid
}t;
struct segt{
#define mid ((l+r)>>1)
int tr[N<<2],mn[N<<2];
inline void build(int k,int l,int r){
tr[k]=mn[k]=1e9+1;
if(l==r){
return;
}
build(k*2,l,mid);
build(k*2+1,mid+1,r);
}
inline void un(int k){
tr[k]=min(tr[k*2],tr[k*2+1]);
}
inline void addt(int k,int d){
mn[k]=min(mn[k],d);
tr[k]=min(tr[k],mn[k]);
}
inline void pd(int k){
if(mn[k]<1e9+1){
addt(k*2,mn[k]);
addt(k*2+1,mn[k]);
mn[k]=1e9+1;
}
}
inline void upd(int L,int R,int k,int l,int r,int d){
if(L<=l&&R>=r){
addt(k,d);
return;
}
pd(k);
if(L<=mid){
upd(L,R,k*2,l,mid,d);
}
if(R>mid){
upd(L,R,k*2+1,mid+1,r,d);
}
un(k);
}
inline int ask(int L,int R,int k,int l,int r){
if(L<=l&&R>=r){
return tr[k];
}
pd(k);
int ans=1e9+1;
if(L<=mid){
ans=ask(L,R,k*2,l,mid);
}
if(R>mid){
ans=min(ans,ask(L,R,k*2+1,mid+1,r));
}
return ans;
}
#undef mid
}b;
inline int calc(int i,int mid){
int now=t.ask(rt[i-1],rt[mid],1,1e9+1,m);
int sc=c[mid]-c[i-1];
return now-sc;
}
inline void sol(int l,int r,int ql,int qr){
if(l>r){
return;
}
pr be={-1e18,0};
int mid=(l+r)>>1;
rep(i,ql,min(mid-m+1,qr)){
int res=calc(i,mid);
be=max(be,{res,i});
}
// cout<<mid<<" from "<<be.se<<' '<<be.fi<<"\n";
pre[mid]=be.se;
ans=max(ans,be.fi);
sol(l,mid-1,ql,be.se);
sol(mid+1,r,be.se,qr);
}
signed main(){
// freopen("Trade.in","r",stdin);
// freopen("Trade.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
rep(i,1,n){
cin>>c[i];
c[i]+=c[i-1];
}
rep(i,1,n){
cin>>s[i];
t.ins(rt[i-1],rt[i],1,1e9+1,s[i]);
}
sol(m,n,1,n);
cout<<ans<<"\n";
b.build(1,1,n);
pre[0]=1;
int i=m,j=0;
while(i<=n){
if(calc(pre[i],i)==ans){
b.upd(pre[i],i,1,1,n,t.qry(rt[pre[i]-1],rt[i],1,1e9+1,m));
rep(k,pre[j],pre[i]-1){
if(calc(k,i)==ans){
b.upd(k,i,1,1,n,t.qry(rt[k-1],rt[i],1,1e9+1,m));
}
}
j=i;
}
i++;
}
rep(i,1,n){
cout<<(s[i]>=b.ask(i,i,1,1,n));
}
return 0;
}