[单调栈 线段树] Codeforces 407E Round #239 (Div. 1) E. k-d-sequence

来源:互联网 发布:cf刷等级软件 编辑:程序博客网 时间:2024/05/16 16:21

首先肯定是一段模 d 相同的数
然后枚举左端点 那么右端点应该满足条件 数字不重复出现且 maxvl,rminvl,rrl+k,这个最大最小值是除过 d
也就是

maxvl,rminvl,rrkl

左端点边挪边用单调栈维护最大最小值 入栈出栈就线段树上区间修改一下
然后查询最右边的满足条件的

#include<cstdio>#include<cstdlib>#include<algorithm>#include<map>using namespace std;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=200005;int n,K,d;int a[N];namespace Work{  int ans1=1,ans2=1;  inline void Solve(){    int ans=0;    for (int i=1,j;i<=n;i=j+1){      j=i;      while (j+1<=n && a[i]==a[j+1]) j++;      if (j-i>ans2-ans1 || (j-i==ans2-ans1 && i<ans1))      ans1=i,ans2=j;    }    printf("%d %d\n",ans1,ans2);  }}int T[N<<2],F[N<<2];inline void mark(int x,int a){  T[x]+=a; F[x]+=a;}inline void push(int x){  if (F[x]) mark(x<<1,F[x]),mark(x<<1|1,F[x]),F[x]=0;}inline void Build(int x,int l,int r){  if (l==r) return void(T[x]=-l);  int mid=(l+r)>>1; Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);  T[x]=min(T[x<<1],T[x<<1|1]);}inline void Add(int x,int l,int r,int ql,int qr,int a){  if (ql<=l && r<=qr){ mark(x,a); return; }  push(x);  int mid=(l+r)>>1;  if (ql<=mid) Add(x<<1,l,mid,ql,qr,a);  if (qr>mid) Add(x<<1|1,mid+1,r,ql,qr,a);  T[x]=min(T[x<<1],T[x<<1|1]);}int Ret=0;inline void query(int x,int l,int r,int K){  if (l==r) return void(Ret=l);  push(x); int mid=(l+r)>>1;  if (T[x<<1|1]<=K) query(x<<1|1,mid+1,r,K);  else query(x<<1,l,mid,K);}inline void Query(int x,int l,int r,int ql,int qr,int lim){  if (Ret) return;  if (ql<=l && r<=qr){    if (T[x]<=lim) query(x,l,r,lim);    return;  }  push(x);  int mid=(l+r)>>1;  if (qr>mid) Query(x<<1|1,mid+1,r,ql,qr,lim);  if (ql<=mid) Query(x<<1,l,mid,ql,qr,lim);}map<int,int> nxt;int last[N];int sta1[N],pnt1; //maxint sta2[N],pnt2; //minint ans1=1,ans2=1;inline void Solve(int l,int r){  if (l==r) return;  for (int i=l;i<=r;i++) a[i]=(a[i]+1e9)/d+1;  int R=r+1;  pnt1=pnt2=0; sta1[0]=sta2[0]=r+1;  for (int i=r;i>=l;i--){    if (nxt.count(a[i])) R=min(R,nxt[a[i]]);    while (pnt1 && a[i]>a[sta1[pnt1]]){      Add(1,1,n,sta1[pnt1],sta1[pnt1-1]-1,-a[sta1[pnt1]]);      pnt1--;    }    sta1[++pnt1]=i;    Add(1,1,n,sta1[pnt1],sta1[pnt1-1]-1,a[i]);    while (pnt2 && a[i]<a[sta2[pnt2]]){      Add(1,1,n,sta2[pnt2],sta2[pnt2-1]-1,a[sta2[pnt2]]);      pnt2--;    }    sta2[++pnt2]=i;    Add(1,1,n,sta2[pnt2],sta2[pnt2-1]-1,-a[i]);    Ret=0; Query(1,1,n,i,R-1,K-i);    if (Ret-i>ans2-ans1 || (Ret-i==ans2-ans1 && i<ans1))      ans1=i,ans2=Ret;    nxt[a[i]]=i;  }  nxt.clear();}int main(){  freopen("bug.in","r",stdin);  freopen("bug.out","w",stdout);  read(n);read(K);read(d); for (int i=1;i<=n;i++) read(a[i]);  if (d==0){    Work::Solve();    return 0;  }  Build(1,1,n);  for (int i=1,j;i<=n;i=j+1){    j=i; while (j+1<=n && (a[i]%d+d)%d==(a[j+1]%d+d)%d) j++;    Solve(i,j);  }  printf("%d %d\n",ans1,ans2);  return 0;}
原创粉丝点击