【题解】tty's sequence
前言
祝愿猪猪早日康复。
昨天在 \(202\) 看 QYB 和 LSC 整活(
所以没时间洗衣服了,洗澡的时候都是开水。
所以定了 \(12:00,12:01,12:02\) 三个闹钟想起来洗衣服,然后一觉睡到 \(6:20\),室友人不在,闹钟响了(
当时觉得很奇怪为什么闹钟没响,但是太困了就继续睡了。
结果一起来看手机显示 \(8:49\)!
马上跳起来把眼镜摘了然后叫上 DYY 一起跑。
到机房已经没了半小时了。
可以感觉到已经炸了。
\(res:135pts\)
\(\text{Description}\)
给定一个长度为 \(n\) 的数列以及 \(k\),请求出两个长度 \(\ge k\) 的子串,分别使得子串中的数的 \(\rm or\) 值和 \(\rm and\) 值最大。
- 对于 \(30\%\) 的数据,\(n,k\le100\)。
- 对于另外 \(30\%\) 的数据,\(k\le10\)。
- 对于 \(100\%\) 的数据,\(1\le k\le n\le1000000\),数列中的每个数在 \([0,2^{31}-1]\) 范围内。
\(\text{Solution}\)
我们考虑每一位:
原数 | 0 | 0 | 1 | 1 |
---|---|---|---|---|
新数 | 0 | 1 | 0 | 1 |
\(\rm or\) 值 | 0 | 1 | 1 | 1 |
\(\rm and\) 值 | 0 | 0 | 0 | 1 |
\(\rm or\) 后不可能变小,\(\rm and\) 后不可能变大。
所以 \(\rm or\) 最大就是所有数 \(\rm or\) 起来,\(\rm and\) 最大就是 \(\max\{\) 所有长度为 \(k\) 的子串的 $ \rm and$ 值 \(\}\)
结果看到这个长度为 \(k\) 的子串没想到线段树(
时间复杂度 \(\mathcal{O}((n-k)\log k)\)。
\(\text{Code}\)
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 1e6 + 5;
int a[MAXN];
#define lson pos << 1
#define rson pos << 1 | 1
struct tree
{
int l, r, val;
}t[MAXN << 2];
void pushup(int pos)
{
t[pos].val = t[lson].val & t[rson].val;
}
void build(int pos, int l, int r)
{
t[pos].l = l, t[pos].r = r;
if (l == r)
{
t[pos].val = a[l];
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(pos);
}
int query(int pos, int L, int R)
{
int l = t[pos].l, r = t[pos].r;
if (L <= l && r <= R)
{
return t[pos].val;
}
int mid = (l + r) >> 1, res = 0x7fffffff;
if (L <= mid)
{
res &= query(lson, L, R);
}
if (R > mid)
{
res &= query(rson, L, R);
}
return res;
}
int main()
{
int n, k, ans1 = 0, ans2 = 0;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
{
scanf("%d", a + i);
ans1 |= a[i];
}
printf("%d ", ans1);
build(1, 1, n);
for (int i = 1; i <= n - k + 1; i++)
{
ans2 = max(ans2, query(1, i, i + k - 1));
}
printf("%d\n", ans2);
return 0;
}