【ST表】【單調隊列】Window(jzoj 1326)

Window

jzoj 1326

題目大意

給你一個序列a和一個數k,讓你求a中所有長爲k的子序列的最大值和最小值

輸入樣例

8 3
1 3 -1 -3 5 3 6 7

輸出樣例

-1 -3 -3 -3 3 3
3 3 5 5 6 7

數據範圍
2020%: n\leqslant 500; 50%: n\leqslant 100000;
100100%: n\leqslant 1000000;

解題思路

方法一:
滾動ST表(不多做解釋)

代碼1:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long 
using namespace std;
int n, k, m, r, f[2][1000010], mf[2][1000010];
int main()
{
	memset(mf, 127/3, sizeof(mf));
	memset(f, -127/3, sizeof(f));
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d", &f[0][i]);
		mf[0][i] = f[0][i];
	}
	m = log2(k);
	for (int j = 1; j <= m; ++j)
	{
		memset(mf[j&1], 127/3, sizeof(mf[j&1]));//滾動
		memset(f[j&1], -127/3, sizeof(f[j&1]));
		for (int i = 1; i <= n - (1<<j) + 1; ++i)
		{
			f[j&1][i] = max(f[(j + 1)&1][i], f[(j + 1)&1][i + (1<<(j - 1))]);//st表
			mf[j&1][i] = min(mf[(j + 1)&1][i], mf[(j + 1)&1][i + (1<<(j - 1))]);
		} 
	}
	for (int i = 1; i <= n - k + 1; ++i)
	{
		r = i + k - 1;
		printf("%d ", min(mf[m&1][i], mf[m&1][r - (1<<m) + 1]));//求解
	}
	putchar(10);
	for (int i = 1; i <= n - k + 1; ++i)
	{
		r = i + k - 1;
		printf("%d ", max(f[m&1][i], f[m&1][r - (1<<m) + 1]));
	}
	return 0;
} 

方法二:
我們用單調隊列來存最大/小值,如果不是更優的就丟掉,如果超過了也丟掉

代碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n, m, tail, head, h[1000100], a[1000100];
int main()
{
	scanf("%d %d", &n, &m);
	tail = 0;
	head = 1;
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d", &a[i]);
		if (head <= tail && h[head] < i - m + 1) head++;//如果過了那就丟掉
		while(head <= tail && a[h[tail]] > a[i]) tail--;//如果比前面的小,那前面的丟掉
		h[++tail] = i;//存進去
		if (i >= m) printf("%d ", a[h[head]]);//這樣下來最前面的就是最小的
	}
	tail = 0;
	head = 1;
	putchar(10);
	for (int i = 1; i <= n; ++i)//同上
	{
		if (head <= tail && h[head] < i - m + 1) head++;
		while(head <= tail && a[h[tail]] < a[i]) tail--;
		h[++tail] = i;
		if (i >= m) printf("%d ", a[h[head]]);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章