CF407E k-d-sequence

Description

给定序列 \({a_n}\),求最长的区间,使得至多添加 \(k\) 个数后,重新排序后是一个公差为 \(d\) 的等差数列。

Solution

先特判掉 \(d=0\) 的情况,添数是无用的,只需要求最长的相同的段即可。

\(d\neq 0\) ,由于是等差数列,所以\(\bmod d\) 的值应该相同,先预处理出膜 \(d\) 值相同的一段,然后提出来单独考虑。

一段区间合法当且仅当值域连续,无重复,并且至的个数小于等于区间长度加 \(k\)

无重复只需要移动左端点,后面的限制可以列成

\[max-min+1\leq (r-l+1+k)*d \]

只需要找到满足条件的最小的 \(l\) 即可,容易发现可以用单调栈和线段树维护。

#include<stdio.h>
#include<algorithm>
#include<map>
using namespace std;

typedef long long ll;

inline int read(){
    int x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

const int N=2e5+7;

int n,k,d;
int a[N],v[N],c[N],ansl,ansr,ans,t[N<<2],tag[N<<2];
int tp1,tp2,st1[N],st2[N];
map<int,int> b;

#define lid id<<1
#define rid id<<1|1

void Add(int id,int val){t[id]+=val,tag[id]+=val;}
void pd(int id){if(tag[id])Add(lid,tag[id]),Add(rid,tag[id]),tag[id]=0;}

int L,R,Val;
void modify(int id,int lf,int rf){
    if(L<=lf&&rf<=R) Add(id,Val);
    else{
        pd(id); int mid=(lf+rf)>>1;
        if(L<=mid) modify(lid,lf,mid);
        if(R>mid) modify(rid,mid+1,rf);
        t[id]=min(t[lid],t[rid]);
    }
}

int check(int id,int lf,int rf){
    if(lf==rf) return lf;
    pd(id); int mid=(lf+rf)>>1;
    if(t[lid]<=Val) return check(lid,lf,mid);
    else return check(rid,mid+1,rf);
}

int query(int id,int lf,int rf){
    if(L<=lf&&rf<=R)
        return t[id]<=Val? check(id,lf,rf):-1;
    pd(id); int mid=(lf+rf)>>1,ret=-1;
    if(L<=mid) ret=query(lid,lf,mid);
    if(~ret) return ret;
    return R>mid? query(rid,mid+1,rf):-1;
}

inline void calc(int l,int r){
    int hd=l;
    st1[0]=st2[0]=l-1,tp1=tp2=0;
    for(int i=l;i<=r;i++){
        b[v[i]]++;
        while(b[v[i]]>1) b[v[hd]]--,hd++;
        while(tp1&&v[st1[tp1]]>=v[i])
            Val=v[st1[tp1]]-v[i],L=st1[tp1-1]+1,R=st1[tp1],modify(1,1,n),tp1--;
        while(tp2&&v[st2[tp2]]<=v[i])
            Val=v[i]-v[st2[tp2]],L=st2[tp2-1]+1,R=st2[tp2],modify(1,1,n),tp2--;
        st1[++tp1]=i,st2[++tp2]=i;
        L=R=Val=i,modify(1,1,n); 
        L=hd,R=i,Val=i+k; int x=query(1,1,n);
        if(i-x+1>ans) ansl=x,ansr=i,ans=i-x+1;
    }
    for(int i=hd;i<=r;i++) b[v[i]]=0;
}

int main(){
    n=read(),k=read(),d=read();
    if(!d){
        int l=1,r=1;
        for(int i=1,tot=0,ans=0,lt=0;i<=n;i++){
            int x=read();
            if(x==lt) tot++;
            else tot=1;
            if(tot>ans) ans=tot,r=i,l=i-tot+1;
            lt=x;
        }
        printf("%d %d",l,r);
    }else{
        for(int i=1,l=1;i<=n+1;i++){
            if(i!=n+1)
                a[i]=read(),c[i]=(a[i]%d+d)%d,v[i]=(a[i]-c[i])/d;
            else c[i]=-1;
            if(i!=1&&c[i]!=c[i-1]) calc(l,i-1),l=i;
        }
        printf("%d %d",ansl,ansr);
    }
}
posted @ 2021-08-20 16:39  Kreap  阅读(34)  评论(0编辑  收藏  举报