有趣的题目名称,有趣的题目

[BZOJ4491]我也不知道题目名字是什么

试题描述

给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串

输入

第一行n,表示A数组有多少元素
接下来一行为n个整数A[i]
接下来一个整数Q,表示询问数量
接下来Q行,每行2个整数l,r

输出

对于每个询问,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串

输入示例

9
1 2 3 4 5 6 5 4 3
5
1 6
1 7
2 7
1 9
5 9

输出示例

6
6
5
6
4

数据规模及约定

对于100%的数据,m<=5n,任意时刻,每个地点的刷卡机台数不超过10000。N<=1.5×105

题解

因为“不上升”或“不下降”是独立的,我们先只考虑不下降的情况。

容易发现不下降的区间是没有交集的,所以从左往右依次给每个不下降区间标号,并维护每个标号的个数,那么对于询问[ql, qr],令L = ql位置的标号,R = qr位置的标号,则有:

answer = qr - ql + 1 (L = R)

answer = max{ [ql, qr]中L标号的个数, [ql, qr]中R标号个数, 标号L+1~R-1个数的最大值 } (L < R)

对于不上升也是一样的。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#include <cstdlib>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
    if(Head == tail) {
        int l = fread(buffer, 1, BufferSize, stdin);
        tail = (Head = buffer) + l;
    }
    return *Head++;
}
int read() {
	int x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
	return x * f;
}

#define maxn 50010
#define maxlog 17
int n, q, A[maxn], up[maxn], U[maxn], stU[maxn], enU[maxn], down[maxn], D[maxn], stD[maxn], enD[maxn];

int qu[maxlog][maxn], qd[maxlog][maxn], Log[maxn];
void init(int* a, int n, int b[][maxn]) {
	for(int i = 1; i <= n; i++) b[0][i] = a[i];
	for(int j = 1; (1 << j) <= n; j++)
		for(int i = 1; i + (1 << j) - 1 <= n; i++)
			b[j][i] = max(b[j-1][i], b[j-1][i+(1<<j-1)]);
	return ;
}
int query(int ql, int qr, int b[][maxn]) {
	if(ql > qr) return -1;
	int l = qr - ql + 1, t = Log[l];
	return max(b[t][ql], b[t][qr-(1<<t)+1]);
}

int main() {
	n = read();
	for(int i = 1; i <= n; i++) A[i] = read();
	
	up[1] = 1; U[1] = 1; stU[1] = enU[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(A[i] >= A[i-1]) up[i] = up[i-1];
		else up[i] = up[i-1] + 1;
		U[up[i]]++;
		if(!stU[up[i]]) stU[up[i]] = i;
		enU[up[i]] = i;
	}
	down[1] = 1; D[1] = 1; stD[1] = enD[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(A[i] <= A[i-1]) down[i] = down[i-1];
		else down[i] = down[i-1] + 1;
		D[down[i]]++;
		if(!stD[down[i]]) stD[down[i]] = i;
		enD[down[i]] = i;
	}
	Log[1] = 0;
	for(int i = 2; i <= n; i++) Log[i] = Log[i>>1] + 1;
	init(U, up[n], qu);
	init(D, down[n], qd);
	
	q = read();
	while(q--) {
		int ql = read(), qr = read();
		int l = up[ql], r = up[qr], ll = down[ql], rr = down[qr];
		int ans = min(max(max(query(l+1, r-1, qu), query(ll+1, rr-1, qd)), max(max(enU[l] - ql + 1, qr - stU[r] + 1), max(enD[ll] - ql + 1, qr - stD[rr] + 1))), qr - ql + 1);
		printf("%d
", ans);
	}
	
	return 0;
}
原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5383180.html