• 多校联训 优美值 题解


    题面:

    一个长度为 n 的序列,对于每个位置 i 的数 ai都有一个优美值,其定义是:找到序列中最长的一段 [l, r],满足 l ≤ i ≤ r,且 [l, r] 中位数为 ai (我们比较序列中两个位置的数的大小时,以数值为第一关键字,下标为第二关键字比较。这样的话 [l, r] 的长度只有可能是奇数),r - l+ 1 就是 i 的优美值。

    接下来有 Q 个询问,每个询问 [l, r] 表示查询区间 [l, r] 内优美值的最大值。

    【输入】

    第一行输入整数n ,第二行输入n 个整数ai ,第三行输入整数 Q,代表有 Q 个区间,接下来 Q 行,每行两个整数 l, r(l ≤ r),表示区间的左右端点。

    【输出】

    对于每个区间的询问,输出答案

    【数据范围】

    对于 30% 的数据,满足 n,Q ≤ 50

    对于 70% 的数据,满足 n,Q ≤ 2000

    对于所有数据,满足 n ≤ 2000, Q ≤ 1000000,ai ≤ 1000000

    首先我们会想到一个十分简单的但非正解做法:n^nlogn+一大堆常数通过对顶堆来求出每个位置的最大值;然后ST表nlogn处理就好了;

    然后细细挖掘这道题,对于每个位置,把大于他的值变成1,否则变成0,然后求一段最大的区间使得区间总和是0,且包含该点;

    这样n^nlogn+nlogn的算法就优化成了n^n+nlogn;

    下面给出对顶堆的代码:

    #include <bits/stdc++.h>
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    template<class nT>
    inline void read(nT& x)
    {
    	char c;while(c=getchar(),!isdigit(c));
    	x=c^48;while(c=getchar(),isdigit(c)) x=x*10+c-48;
    }
    const int MXR=1e6+1e5;
    int a[MXR];
    priority_queue<pair<int,int> >  q1,q2;//q1是大根堆,q2是小根堆 
    int ans[MXR];
    int f[MXR][25];
    int n; 
    int pre[MXR];
    void build()
    {
    	inc(i,1,n) f[i][0]=ans[i];
    	inc(j,1,20){
    	    for(int i=1;i+(1<<j)-1<=n;i++){
    	    	f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    	    }
    	}
    	inc(j,0,19){
    		inc(i,(1<<j),(1<<(j+1))-1){
    			if(i>MXR) break;
    			pre[i]=j;
    		}
    	}
    }
    int main()
    {
    	read(n);
    	inc(i,1,n) read(a[i]);
    	inc(i,1,n){
    		while(q1.size()) q1.pop();
    		while(q2.size()) q2.pop();
    		inc(j,i,n){
    			if(q1.size()&&a[j]>q1.top().first) q2.push(make_pair(-a[j],j));
    			else q1.push(make_pair(a[j],j));
    			if((j-i+1)%2==0){
    				continue;
    			}
    			while(q2.size()>(j-i+1)/2){
    				q1.push(make_pair(-q2.top().first,q2.top().second));
    				q2.pop();
    			}
    			while(q2.size()<(j-i+1)/2){
    				q2.push(make_pair(-q1.top().first,q1.top().second));
    				q1.pop();
    			}			
    			ans[q1.top().second]=max(ans[q1.top().second],(j-i+1));
    		}
    	}
    	build();
    	int q; read(q);
    	inc(i,1,q){
    		int x,y; read(x); read(y);
    		int logg=pre[y-x+1];
    		int anss=max(f[x][logg],f[y-(1<<logg)+1][logg]);
    		printf("%d
    ",anss);
    	}
    	
    }
    /*
    8
    16 19 7 8 9 11 20 16
    8
    3 8
    1 4
    2 3
    1 1
    5 5
    1 2
    2 8
    7 8
    */
    
  • 相关阅读:
    JAVA流操作
    Ubuntu 14.04 忘记root密码
    产出与产能要平衡-《高效能人士的七个习惯》随笔三
    重新认识自我-《高效能人士的七个习惯》随笔二
    高效能人士的七个习惯 随笔一
    松下A6伺服器通信设定
    未能加载文件或程序集 或它的某一个依赖项。试图加载格式不正确的程序。问题解决
    keil中出现Undefined symbol FLASH_PrefetchBufferCmd (referred from main.o)等问题解决办法
    c语言中static的用法,包括全局变量和局部变量用static修饰
    STM32启动文件详细解析(V3.5.0) 以:startup_stm32f10x_hd.s为例
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11747505.html
Copyright © 2020-2023  润新知