zoukankan      html  css  js  c++  java
  • CF407E k-d-sequence

    Description

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

    Solution

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

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

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

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

    [max-min+1leq (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);
        }
    }
    
  • 相关阅读:
    leetcode 29-> Divide Two Integers without using multiplication, division and mod operator
    ros topic 发布一次可能会接收不到数据
    python中的print()、str()和repr()的区别
    python 部分函数
    uiautomatorviewer错误 unable toconnect to adb
    pyqt 不规则形状窗口显示
    appium 计算器demo
    Spring 3.0 注解注入详解
    Spring Autowire自动装配
    restful 学习地址
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15158580.html
Copyright © 2011-2022 走看看