• CH134 双端队列 题解报告


    题目传送门

    【题目大意】

    用若干个双端队列给$N$个整数排序,依次处理这$N$个数,对于每个数$A_i$,可以进行两种操作:

    1.新建一个双端队列,并将$A_i$作为这个队列中唯一的数

    2.把$A_i$从已有队列的队头或队尾入队

    对所有的数处理完后,要求这些队列能够按照一定的顺序连接起来,得到一个非降的长度为$N$的序列,求最少需要多少个双端队列。

    【思路分析】

    我们把问题反过来思考,先把$N$个数从小到大排序,然后分成尽量少的几段,对应原问题中的合法双端队列。

    易知一个结论,对于排序后每个位置的数原本的下标组成的序列$B$,如果一段满足单谷性质(即先递减后递增),那么这一段就对应原问题中的一个合法双端队列。(递减的一段相当于从队头插入,递增的一段相当于从队尾插入)

    还要注意一点,就是如果存在相同的几个数,那么它们排序后的位置是随机的,可以看成一个整体来处理。如果这个整体中最小的下标大于前面的序列中最大的下标,那么满足递增;如果这个整体中最大的下标小于前面的序列中最小的下标,那么满足递减。

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define g() getchar()
     7 #define rg register
     8 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     9 #define back(i,a,b) for(rg int i=a;i>=b;i--)
    10 #define db double
    11 #define ll long long
    12 #define il inline
    13 #define pf printf
    14 using namespace std;
    15 int fr(){
    16     int w=0,q=1;
    17     char ch=g();
    18     while(ch<'0'||ch>'9'){
    19         if(ch=='-') q=-1;
    20         ch=g();
    21     }
    22     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
    23     return w*q;
    24 }
    25 const int N=200002;
    26 int n;
    27 struct number{
    28     int a,id;
    29 }d[N];
    30 struct line{
    31     int minn,maxn;
    32 }l[N];
    33 il bool cmp(number x,number y){
    34     return x.a<y.a; 
    35 }
    36 int main(){
    37     //freopen("","r",stdin);
    38     //freopen("","w",stdout);
    39     n=fr();
    40     go(i,1,n) d[i].a=fr(),d[i].id=i;
    41     sort(d+1,d+1+n,cmp);
    42     rg int num=0;
    43     go(i,1,n){//先处理一下相同的数字
    44         l[++num].minn=d[i].id,l[num].maxn=d[i].id;
    45         while(d[i].a==d[i+1].a){
    46             i++;
    47             l[num].minn=min(l[num].minn,d[i].id);
    48             l[num].maxn=max(l[num].maxn,d[i].id);
    49         }
    50     }
    51     bool now=0;rg int ans=1;
    52     go(i,2,num){
    53         if(now){//递增
    54             if(l[i].minn>l[i-1].maxn) continue;
    55             else ans++,now=0;
    56         }
    57         else{//递减
    58             if(l[i].maxn<l[i-1].minn) continue;
    59             else now=1;
    60         }
    61     }
    62     pf("%d
    ",ans);
    63     return 0;
    64 }
    代码戳这里
  • 相关阅读:
    php接收二进制文件转换成图片
    浅述WinForm多线程编程与Control.Invoke的应用
    精典策略模式
    js数组的操作详解
    PHP常用类
    收藏:五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT)
    在 Windows 上部署 Qt 应用程序
    解决 MinGW5.14 编译 QT4.4.3 报错的问题
    懒人制作 deb 包
    NET 自定义配置文件 Configuration
  • 原文地址:https://www.cnblogs.com/THWZF/p/11362686.html
Copyright © 2020-2023  润新知