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


    [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;
    }
    
  • 相关阅读:
    MFC下使用Mysql
    Curl的移植编译以及注意事项
    MFC 封装类为静态链接库
    MFC 任务托盘显示气泡
    MFC 获取本机IP、网络ip和物理地址
    MFC下获取系统内存和当前进程的内存使用情况
    C++ windows客户端支持SSL双向认证
    jdk+tomcat+mysql一键安装脚本
    mysql修改数据库密码
    MFC 任务托盘经常消失问题
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5383180.html
Copyright © 2020-2023  润新知