题解 End Sky II
连套路题都做不出来了,自闭了
发现这个取与运算比较麻烦,考虑枚举最终答案来 check
如果最终答案确定了,那么所有是它母集的 \(a_i\) 都可以做合法的最大值
于是考虑用 DP 出这些点最多能将原序列分为多少段
处理出每个位置左右第一个大于它的位置,线段树优化 DP 一下即可
然后 check \(f_n\geqslant k\)
发现这样就可以逐位确定了
复杂度 \(O(n\log n\log V)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k;
int a[N];
// namespace task1{
// const int SIZE=520;
// bitset<SIZE> f[N][N], ans;
// struct Seg{
// #define tl(p) tl[p]
// #define tr(p) tr[p]
// #define val(p) val[p]
// #define pushup(p) val(p)=val(p<<1)|val(p<<1|1)
// int tl[N<<2], tr[N<<2];
// bitset<SIZE> val[N<<2];
// void build(int p, int l, int r) {
// tl(p)=l; tr(p)=r;
// if (l==r) return ;
// int mid=(l+r)>>1;
// build(p<<1, l, mid);
// build(p<<1|1, mid+1, r);
// }
// void upd(int p, int pos, bitset<SIZE>& dat) {
// if (tl(p)==tr(p)) {val(p)=dat; return ;}
// int mid=(tl(p)+tr(p))>>1;
// if (pos<=mid) upd(p<<1, pos, dat);
// else upd(p<<1|1, pos, dat);
// pushup(p);
// }
// bitset<SIZE> query(int p, int l, int r) {
// if (l<=tl(p)&&r>=tr(p)) return val(p);
// int mid=(tl(p)+tr(p))>>1;
// if (l<=mid&&r>mid) return query(p<<1, l, r)|query(p<<1|1, l, r);
// else if (l<=mid) return query(p<<1, l, r);
// else return query(p<<1|1, l, r);
// }
// }seg[N];
// void solve() {
// // cout<<double(sizeof(seg)+sizeof(f))/1000/1000<<endl;
// int lim=1<<9;
// for (int i=0; i<=k; ++i) seg[i].build(1, 0, n);
// for (int s=0; s<lim; ++s) f[0][0][s]=1;
// seg[0].upd(1, 0, f[0][0]);
// for (int j=1; j<=n; ++j) {
// //cout<<"j: "<<j<<endl;
// int lst=0;
// for (int i=1; i<j; ++i) if (a[i]>a[j]) lst=i;
// //cout<<"lst: "<<lst<<endl;
// for (int i=1; i<=k; ++i) {
// //cout<<"i: "<<i<<endl;
// f[i][j]|=seg[i-1].query(1, lst, j-1);
// //cout<<1<<endl;
// //cout<<"g["<<i<<"]["<<j<<"]: "<<f[i][j]<<endl;
// for (int s=1; s<lim; ++s) if ((s&a[j])!=s) f[i][j][s]=0; //, cout<<s<<endl;
// //cout<<"f["<<i<<"]["<<j<<"]: "<<f[i][j]<<endl;
// for (int s=lim-1; s; --s) {
// for (int t=0; t<9; ++t) if (!(s&(1<<t))) {
// if (f[i][j][s|(1<<t)]) f[i][j][s]=1;
// }
// }
// seg[i].upd(1, j, f[i][j]);
// //cout<<"f["<<i<<"]["<<j<<"]: "<<f[i][j]<<endl;
// }
// }
// int lst=0, now=0;
// for (int i=n; i; --i) {
// if (a[i]>=lst) ans|=seg[k].query(1, i, i);
// lst=max(lst, a[i]);
// }
// for (int i=ans._Find_first(); i<SIZE; i=ans._Find_next(i)) now=i;
// printf("%d\n", now);
// }
// }
namespace task{
bool vis[N];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define val(p) val[p]
#define tag(p) tag[p]
#define pushup(p) val(p)=max(val(p<<1), val(p<<1|1))
int tl[N<<2], tr[N<<2], val[N<<2], tag[N<<2], l[N], r[N], sta[N], ans;
inline void spread(int p) {
if (!tag(p)) return ;
val(p<<1)=max(val(p<<1), tag(p)); tag(p<<1)=max(tag(p<<1), tag(p));
val(p<<1|1)=max(val(p<<1|1), tag(p)); tag(p<<1|1)=max(tag(p<<1|1), tag(p));
tag(p)=0;
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r; val(p)=tag(p)=0;
if (l==r) {val(p)=0; return ;}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
}
void upd(int p, int l, int r, int dat) {
if (l<=tl(p)&&r>=tr(p)) {val(p)=max(val(p), dat); tag(p)=max(tag(p), dat); return ;}
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) upd(p<<1, l, r, dat);
if (r>mid) upd(p<<1|1, l, r, dat);
pushup(p);
}
int query(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) return val(p);
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid&&r>mid) return max(query(p<<1, l, r), query(p<<1|1, l, r));
else if (l<=mid) return query(p<<1, l, r);
else return query(p<<1|1, l, r);
}
void solve() {
for (int i=1,top=0; i<=n; ++i) {
while (top && a[sta[top]]<=a[i]) --top;
if (top) l[i]=sta[top];
sta[++top]=i;
}
for (int i=n,top=0; i; --i) {
while (top && a[sta[top]]<=a[i]) --top;
if (top) r[i]=sta[top];
else r[i]=n+1;
sta[++top]=i;
}
//cout<<"l: "; for (int i=1; i<=n; ++i) cout<<l[i]<<' '; cout<<endl;
//cout<<"r: "; for (int i=1; i<=n; ++i) cout<<r[i]<<' '; cout<<endl;
for (int i=30; ~i; --i) {
for (int j=1; j<=n; ++j)
if ((a[j]&(ans|(1<<i)))==(ans|(1<<i))) vis[j]=1;
else vis[j]=0;
build(1, 0, n);
for (int j=1; j<=n; ++j) if (vis[j])
upd(1, j, r[j]-1, query(1, l[j], j)+1);
if (query(1, n, n)>=k) ans|=1<<i;
}
cout<<ans<<endl;
}
}
signed main()
{
freopen("sky.in", "r", stdin);
freopen("sky.out", "w", stdout);
n=read(); k=read();
for (int i=1; i<=n; ++i) a[i]=read();
task::solve();
return 0;
}