ARC098C
传送门
看起来是有一种\(O(n^2)\)的做法的,不过只想到了\(O(n^2logn)\)的做法。
不难想到,如果能够确定最终删去的最小值,只需要确定最大值就能得到答案了,于是不妨去枚举这个删去的最小值。
假设当前枚举的最小值是\(x\),从小到大,依次去check比\(x\)大的数\(y\)能否被删除,它能被删除的条件为存在一个长为\(K\)的区间,\(y\)是其中的最小值。
可以从\(y\)的下标\(pos\)出发,找到最左端的\(l\)使得区间\([l,pos]\)的最小值是\(y\),同理找到另一端\(r\)。如果满足\(r-l+1\geq K\),就证明可以删除。
可以在线段树上二分实现上面的操作,并不难,就不赘述如何二分了。
而删除操作则可以改为单点修改,把这个点的值改为\(inf\),并打上一个标记,表示当前这个点被删除了。于是上面的条件就变成了\(r-l+1-\texttt{区间中被打上标记的点的个数}\geq K\)
最后记录一下对于不同的最小值的答案,取个\(min\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define ll long long
#define ui unsigned int
il ll read(){
bool f=true;ll x=0;
register char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=false;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
if(f) return x;
return ~(--x);
}
il int read(char *s){
int len=0;
register char ch=getchar();
while(ch==' '||ch=='\n') ch=getchar();
while(ch!=' '&&ch!='\n'&&ch!=EOF) s[++len]=ch,ch=getchar();
return len;
}
il void write(const ll &x){if(x>9) write(x/10);putchar(x%10+'0');}
il void print(const ll &x) {x<0?putchar('-'),write(~(x-1)):write(x);putchar('\n');}
il ll max(const ll &a,const ll &b){return a>b?a:b;}
il ll min(const ll &a,const ll &b){return a<b?a:b;}
const int MAXN=2e3+7;
ll n,m,k,a[MAXN];
#define lc (u<<1)
#define rc (u<<1|1)
struct SegT
{
struct T
{
int l,r;
ll cnt,mn;
}t[MAXN<<2];
il void update(int u){
t[u].mn=min(t[lc].mn,t[rc].mn);
t[u].cnt=t[lc].cnt+t[rc].cnt;
}
il void change(int u,int pos,ll v,ll w=0){
if(t[u].l==pos&&t[u].r==pos){
t[u].mn=v,t[u].cnt+=w;
return;
}
int mid=(t[u].l+t[u].r)>>1;
if(pos<=mid) change(lc,pos,v,w);
else change(rc,pos,v,w);
update(u);
}
il ll query_l(int u,int l,int r,ll v){
if(t[u].mn>=v) return min(l,t[u].l);
if(!u) return 1e9;
if(t[u].l==t[u].r){
if(t[u].mn<v) return 1e9;
return t[u].l;
}
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid) return query_l(lc,l,r,v);
else if(l>mid) return query_l(rc,l,r,v);
else{
ll res=query_l(rc,mid+1,r,v);
if(res==mid+1) return min(res,query_l(lc,l,mid,v));
else return res;
}
}
il ll query_r(int u,int l,int r,ll v){
if(t[u].mn>=v) return max(r,t[u].r);
if(!u) return 0;
if(t[u].l==t[u].r){
if(t[u].mn<v) return 0;
return t[u].l;
}
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid) return query_r(lc,l,r,v);
else if(l>mid) return query_r(rc,l,r,v);
else{
ll res=query_r(lc,l,mid,v);
if(res==mid) return max(res,query_r(rc,mid+1,r,v));
else return res;
}
}
il ll query(int u,int l,int r){
if(!t[u].cnt) return 0;
if(t[u].l==l&&t[u].r==r)
return t[u].cnt;
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid) return query(lc,l,r);
else if(l>mid) return query(rc,l,r);
else return query(lc,l,mid)+query(rc,mid+1,r);
}
il void build(int u,int l,int r){
t[u].l=l,t[u].r=r;
if(l==r){
t[u].mn=a[l];
t[u].cnt=0;
return;
}
int mid=(t[u].l+t[u].r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
update(u);
}
il void renew(int u,int l,int r){
if(l==r){
t[u].mn=a[l];
t[u].cnt=0;
return;
}
int mid=(t[u].l+t[u].r)>>1;
if(t[lc].cnt)renew(u<<1,l,mid);
if(t[rc].cnt)renew(u<<1|1,mid+1,r);
update(u);
}
}T;
struct node
{
ll pos,v;
bool operator<(const node &x)const{
return v==x.v?pos<x.pos:v<x.v;
}
};
vector<node> vec;
bool check(int pos){
int l=T.query_l(1,1,pos,a[pos]),r=T.query_r(1,pos,n,a[pos]);
if(r-l+1<m||r-l+1-T.query(1,l,r)<m) return false;
return true;
}
ll ans=1e18;
int main(){
// freopen("rand.in","r",stdin);
// freopen("1.out","w",stdout);
n=read(),m=read(),k=read();
for(ri i=1;i<=n;++i) a[i]=read(),vec.push_back((node){i,a[i]});
vec.push_back((node){0,0});
sort(vec.begin(),vec.end());
T.build(1,1,n);
for(ri i=1;i<=n;++i){
T.renew(1,1,n);
ll now=0,res=1e18;
if(!check(vec[i].pos)) continue;
for(ri j=i;j<=n&&now<k;++j){
if(check(vec[j].pos)){
res=vec[j].v;
T.change(1,vec[j].pos,1e10,1);
++now;
}
}
if(now<k) continue;
ans=min(ans,res-vec[i].v);
}
print(ans);
return 0;
}

浙公网安备 33010602011771号