[jzoj4665][CF407E]k-d-sequence
来源:互联网 发布:unity3d小球滚动 编辑:程序博客网 时间:2024/06/01 10:36
题目大意
给你一个长度为n的序列a[],两个参数k,d,求序列最长的一段,使得这一段所有的数升序排序后最多再加上k个任意的数,可以构成公差为d的等差数列。输出这一段的两端。
n<=2*10^5, 0<=k<=2*10^5, d,|a[i]|<=10^9
分析
首先有个很显然的结论嘛,答案的那一段区间所有数,两两之间的差都是d的倍数,而且互不相同。那么前者等价于相邻的差是d的倍数,于是乎我们可以把原序列切成许多段,每一段的数相邻的差都是d的倍数。
后者可以设mxright[x]表示最大的满足a[x~mxright[x]]互不相同的值,求答案的时候限制一下就好了。
现在考虑一段上怎么做。
为了看起来好看,激发我们的灵感,我们可以先处理一下数据。对于一段每个数a[x],令a[x]=(a[x]-min)/d+1,min即为这一段的最小值。
接下来怎么做?二分长度?不行,不满足二分性质。
考虑一下暴力如何求解先吧!枚举左右端点l,r,满足什么样的条件可以更新答案呢?
即max{a[l~r]}-min{a[l~r]}+1≤r-l+1+k。
而做这些题的套路,一般是枚举一个左端点,看看合法最远右端点在哪里。
我们化一下上面的式子,max{a[l~r]}-min{a[l~r]}-r≤k-l
这样右边就只与左端点有关了。
我们考虑枚举左端点l。这时设mx[r]=max{a[l~r]},mn[r]=min{a[l~r]},很容易发现mx是不下降的,mn是不上升的,是不是可以维护一下他们呢?设b[r]=mx[r]-mn[r]-r;看一下怎么维护它,加入能维护,那么我们只要找最大的r,满足b[r]≤k-l。
倒着枚举左端点,这样可以让mx只会变大而不缩小,更好维护;mn同理。考虑l变成l-1会发生什么?就是mx(mn)中,大于(小于)a[l-1]的,全部变为a[l-1]。哎,我们发现会出现一块一块的东西,以后修改的时候不就可以区间修改了?因此我们用栈记录每种值出现的一块的位置,这样到时候更新mx(mn)就很方便了,每次弹出一块,区间加(减)。事实上,我们只用线段树维护b就好了。
那么整理一下做法:枚举右端点l,用线段树维护b数组,区间加减,区间位置由栈来维护。寻找最大r满足b[r]≤k-l,且r≤mxright[l]。时间复杂度O(nlogn)
代码
打的时候生病了,很乱。
#include<cstdio>#include<algorithm>#include<cstring>#include<map>using namespace std;typedef long long ll;#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)const int M=200005,mx=1e9+7,N=1e8+7;struct rec{ int mn,tag;}tr[M*5];int a[M],n,K,d,sta1[M],sta2[M],b[M],t1,t2,i,j,k,l,r,L,R,tt,mn,ans,x,maxr[M],dur;//store posmap<int,int> pos;void down(int x,int l,int r){ if (l!=r) { tr[x*2].tag+=tr[x].tag; tr[x*2+1].tag+=tr[x].tag; } tr[x].mn+=tr[x].tag; tr[x].tag=0;}void downdate(int x,int l,int r,int m){ down(x,l,r); if (l!=r) { down(x*2,l,m); down(x*2+1,m+1,r); } if (l!=r) tr[x].mn=min(tr[x*2].mn,tr[x*2+1].mn);}void make(int x,int l,int r){ tr[x].mn=N; if (l==r) return; int m=(l+r)/2; make(x*2,l,m); make(x*2+1,m+1,r);}void change(int x,int l,int r,int i,int j,int val){ int m=(l+r)/2; if (l==i&&r==j) { tr[x].tag+=val; downdate(x,l,r,m); return; } downdate(x,l,r,m); if (j<=m) change(x*2,l,m,i,j,val); else if (i>m) change(x*2+1,m+1,r,i,j,val); else { change(x*2,l,m,i,m,val); change(x*2+1,m+1,r,m+1,j,val); } tr[x].mn=min(tr[x*2].mn,tr[x*2+1].mn);}void maintain_mx(int x){ while (t1&&a[x]>a[sta1[t1]]) { change(1,1,n,sta1[t1],sta1[t1-1]-1,a[x]-a[sta1[t1]]); sta1[t1--]=0; } sta1[++t1]=x;}void maintain_mn(int x){ while (t2&&a[x]<a[sta2[t2]]) { change(1,1,n,sta2[t2],sta2[t2-1]-1,a[sta2[t2]]-a[x]); sta2[t2--]=0; } sta2[++t2]=x;}int find(int x,int l,int r,int val){ int m=(l+r)/2; downdate(x,l,r,m); if (tr[x].mn>val) return 0; if (l==r) return l; if (tr[x*2+1].mn<=val) return find(x*2+1,m+1,r,val); else return find(x*2,l,m,val);}int main(){ //freopen("t0.in","r",stdin); scanf("%d %d %d",&n,&K,&d); fo(i,1,n) scanf("%d",a+i); R=r=n; //make(1,1,n); b[++b[0]]=n; sta1[0]=n+1; sta2[0]=n+1; fd(i,n,1) { if (a[i]==a[i+1]) tt++; else tt=1; if ((!d)&&tt>=ans) { ans=tt; L=i; } if (x=pos[a[i]]) r=min(x-1,r); pos[a[i]]=i; maxr[i]=r; if (d&&((a[i]%d+d)%d!=(a[i-1]%d+d)%d||i==1)) { b[++b[0]]=i-1; r=i-1; mn=mx; fo(j,i,R) mn=min(mn,a[j]); fo(j,i,R) a[j]=(a[j]-mn)/d+1; R=i-1; } } R=n; if (d) fo(k,1,b[0]) { //clear(); fd(i,b[k],b[k+1]+1) { // a[i] if (i==1) { i=1; } maintain_mx(i); maintain_mn(i); if (R>maxr[i]) { change(1,1,n,maxr[i]+1,R,N); R=maxr[i]; } change(1,1,n,i,i,-i);//mx-mn-r dur=find(1,1,n,K-i);// find the rightermost one which is less than k-l if (dur-i+1>=ans) { ans=dur-i+1; L=i; } } } //min max for b[i] l-- r query change add delete printf("%d %d\n",L,L+ans-1);}
- [jzoj4665][CF407E]k-d-sequence
- [CF407E]k-d-sequence
- bzoj4527: K-D-Sequence
- [bzoj4527]K-D-Sequence 解题报告
- [codeforces 407E]k-d-sequence
- 【 bzoj 4527 && CF 407 E】K-D-Sequence
- [单调栈 线段树] Codeforces 407E Round #239 (Div. 1) E. k-d-sequence
- [线段树][单调栈] BZOJ 4527 && CF 407E: K-D-Sequence
- k-flat sequence
- D - Colour sequence
- 【CODEFORCES】 D. Increase Sequence
- D - BestCoder Sequence
- poj 3709 K-Anonymous Sequence
- Fibonacci sequence of k order
- POJ 3709 K-Anonymous Sequence
- POJ 3709 K-Anonymous Sequence
- poj 3709 K-Anonymous Sequence
- problem K.Reisen's sequence
- [codeforces117E]Tree or not Tree
- 搭建一个spring-boot项目 4
- hduoj-2824【欧拉函数】
- List.addAll()操作总结
- CodeForces
- [jzoj4665][CF407E]k-d-sequence
- 个人对this总结
- bzoj1634
- 云计算与数据中心
- Java Groovy集成
- 服务端主动终止连接的情况分析
- Linux find指令
- 3.6 Git 分支
- Android比较流行框架学习