题解 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;
}
posted @ 2022-02-22 16:54  Administrator-09  阅读(2)  评论(0编辑  收藏  举报