[JZOJ5185] 【NOIP2017提高组模拟6.30】tty's sequence
或的最大值一定是全部或起来。
与的最大值一定是k个与起来, 于是用线段树维护区间与值, 然后暴力枚举起点。
复杂度O(NlogN);
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; inline int read() { int res=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return res; } #define reg register int n, k; int a[1000005]; long long ans, res; int tr[1000005<<2]; #define ls(o) o << 1 #define rs(o) o << 1 | 1 void Build(int l, int r, int o) { if (l == r) { tr[o] = a[l]; return ; } int mid = l + r >> 1; Build(l, mid, ls(o)); Build(mid + 1, r, rs(o)); tr[o] = tr[ls(o)] & tr[rs(o)]; } void query(int l, int r, int o, int ql, int qr) { if (l >= ql and r <= qr) { res &= tr[o]; return ; } int mid = l + r >> 1; if (mid >= ql) query(l, mid, ls(o), ql, qr); if (mid < qr) query(mid + 1, r, rs(o), ql, qr); } int main() { n = read(), k = read(); for (reg int i = 1 ; i <= n ; i ++) a[i] = read(), ans |= a[i]; printf("%lld ", ans); Build(1, n, 1); ans = 0; for (reg int i = 1 ; i <= n - k + 1 ; i ++) { res = (1ll << 31) - 1; query(1, n, 1, i, i + k - 1); ans = max(ans, res); } printf("%lld\n", ans); return 0; }