[l,r]+x不如[l,n]+x
[l,r]-x不如(r,n)+x
所以等价于只有[l,n]+x
枚举断点树状数组合并
难度在于想到这个贪心
#include<cstdio> #include<algorithm> using namespace std; int cnt,n,x,A[1000005],stack[1000005],F[1000005],E[1000005],S[1000005],T[1000005],a[1000005],tree[1000005]; void solve(){ int tail=0; stack[0]=-1e9; for (int i=1; i<=n; i++){ if (A[i]>stack[tail]) { stack[++tail]=A[i]; F[i]=tail; } else{ int ID=lower_bound(stack+1,stack+tail+1,A[i])-stack; stack[ID]=A[i]; F[i]=ID; } } } int lowbit(int x){ return x&(-x); } void insert(int x,int y){ for (int i=x; i<=cnt; i+=lowbit(i)) tree[i]=max(tree[i],y); } int query(int x){ int ans=0; for (int i=x; i; i-=lowbit(i)) ans=max(ans,tree[i]); return ans; } int main(){ scanf("%d%d",&n,&x); if (x<0) x=-x; for (int i=1; i<=n; i++) scanf("%d",&a[i]); for (int i=1; i<=n; i++) E[++cnt]=a[i]; for (int i=1; i<=n; i++) E[++cnt]=a[i]+x-1; sort(E+1,E+cnt+1); cnt=unique(E+1,E+cnt+1)-E-1; for (int i=1; i<=n; i++) A[i]=a[i]; solve(); for (int i=1; i<=n; i++) S[i]=F[i]; for (int i=1; i<=n/2; i++) swap(A[i],A[n-i+1]); for (int i=1; i<=n; i++) A[i]=-A[i]; solve(); for (int i=1; i<=n; i++) T[i]=F[n-i+1]; int ans=0; for (int i=1; i<=n; i++){ ans=max(ans,T[i]+query(lower_bound(E+1,E+cnt+1,a[i]+x-1)-E)); insert(lower_bound(E+1,E+cnt+1,a[i])-E,S[i]); } printf("%d ",ans); return 0; }