1. 程式人生 > 其它 >【題解】tty's sequence

【題解】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;
}