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;
}
posted @ 2021-03-01 19:22  krimson  阅读(119)  评论(0)    收藏  举报