有趣的题目名称,有趣的题目
[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\n", ans);
}
return 0;
}

浙公网安备 33010602011771号