发现右端点固定时,左端点的 \(min-max\) 单调递减,且对于 \(or\) 和 \(and\) 相减,最多有 \(\rm2logn\)个不同的值,且相同的值构成一段连续的区间。
那么就可以在最远的,符合答案的第一个区间二分答案。
具体实现可以用一个链表,每次扫一遍合并,并倒着查合法区间,这样就能做到 \(\rm nlogn\)。
#include<bits/stdc++.h> #define ri register signed #define Re register #define p(i) ++i namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++ struct nanfeng_stream{ template<typename T>inline nanfeng_stream operator>>(T &x) { ri f=0;x=0;register char ch=gc(); while(!isdigit(ch)) f|=ch=='-',ch=gc(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc(); return x=f?-x:x,*this; } }cin; } using IO::cin; namespace nanfeng{ #define node(x,y,z) (node){x,y,z} #define eb emplace_back #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} static const int N=1e6+7; struct node{int l,OR,AND;int val() {return OR-AND;}}; std::list<node> lis; int a[N],stn[N][23],stx[N][23],lg[N],n,k; inline void init_rmq() { for (ri i(1);i<=n;p(i)) stx[i][0]=stn[i][0]=a[i]; for (ri i(2);i<=n;p(i)) lg[i]=lg[i>>1]+1; for (ri j(1);j<19;p(j)) { ri len=1<<j; for (ri i(1);i+len-1<=n;p(i)) { stx[i][j]=cmax(stx[i][j-1],stx[i+(1<<j-1)][j-1]); stn[i][j]=cmin(stn[i][j-1],stn[i+(1<<j-1)][j-1]); } } } inline int Getmx(int l,int r) { int k=lg[r-l+1]; return cmax(stx[l][k],stx[r-(1<<k)+1][k]); } inline int Getmn(int l,int r) { int k=lg[r-l+1]; return cmin(stn[l][k],stn[r-(1<<k)+1][k]); } inline bool check(Re std::list<node>::iterator it,int l,int r) {return it->val()+Getmn(l,r)-Getmx(l,r)>=k;} struct Seg{ #define ls(x) (x<<1) #define rs(x) (x<<1|1) struct segmenttree{int mx,lz;segmenttree(){mx=lz=-1;}}T[N<<2]; inline void down(int x) { int l=ls(x),r=rs(x); T[l].mx=cmax(T[l].mx,T[x].lz); T[r].mx=cmax(T[r].mx,T[x].lz); T[l].lz=cmax(T[l].lz,T[x].lz); T[r].lz=cmax(T[r].lz,T[x].lz); } void update(int x,int l,int r,int lt,int rt) { if (l<=lt&&rt<=r) { T[x].lz=cmax(T[x].lz,r-l+1); T[x].mx=cmax(T[x].mx,r-l+1); return; } down(x); int mid(lt+rt>>1); if (l<=mid) update(ls(x),l,r,lt,mid); if (r>mid) update(rs(x),l,r,mid+1,rt); } void print(int x,int l,int r) { if (l==r) return (void)(printf("%d ",T[x].mx)); int mid(l+r>>1); down(x); print(ls(x),l,mid); print(rs(x),mid+1,r); } }T; inline int main() { //FI=freopen("nanfeng.in","r",stdin); //FO=freopen("nanfeng.out","w",stdout); cin >> n >> k; for (ri i(1);i<=n;p(i)) cin >> a[i]; init_rmq(); for (ri i(1);i<=n;p(i)) { for (Re auto it=lis.begin();it!=lis.end();p(it)) it->OR|=a[i],it->AND&=a[i]; lis.eb(node(i,a[i],a[i])); for (Re auto it1=lis.begin(),it2=next(it1);it2!=lis.end();p(it2)) if (it1->val()==it2->val()) lis.erase(it1),it1=it2; else p(it1); for (Re auto it=lis.begin();it!=lis.end();p(it)) if (check(it,it->l,i)) { ri l=1,r=it->l,res; if (it!=lis.begin()) l=prev(it)->l+1; while(l<=r) { int mid(l+r>>1); if (check(it,mid,i)) r=mid-1,res=mid; else l=mid+1; } T.update(1,res,i,1,n); break; } } T.print(1,1,n); return 0; } } int main() {return nanfeng::main();}