zoukankan      html  css  js  c++  java
  • BZOJ 2457 [BeiJing2011] 双端队列

    2457: [BeiJing2011]双端队列

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 340  Solved: 167
    [Submit][Status][Discuss]

    Description

    Sherry现在碰到了一个棘手的问题,有N个整数需要排序。
    Sherry手头能用的工具就是若干个双端队列。
    她需要依次处理这N个数,对于每个数,Sherry能做以下两件事:
      1.新建一个双端队列,并将当前数作为这个队列中的唯一的数;
      2.将当前数放入已有的队列的头之前或者尾之后。
    对所有的数处理完成之后,Sherry将这些队列排序后就可以得到一个非降的序列。

    Input

    第一行包含一个整数N,表示整数的个数。接下来的N行每行包含一个整数Di,其中Di表示所需处理的整数。

    Output

    其中只包含一行,为Sherry最少需要的双端队列数。

    Sample Input

    6
    3 6 0 9 6 3

    Sample Output

    2

    HINT

    100%的数据中N≤200000。

     
    [Submit][Status][Discuss]

    题解:

      此题手玩了很久,发现了一个对于不重复的元素可行的nlogn的方法。首先给每一个元素编号1~n,然后放在结构体里面sort。例如样例:

    IN:6 1 8 7 4 2 6 OUT:3

      序号变成了1 5 4 6 3 2。可以发现首先对于1号,左右都没有已经加入队列的元素,那么新建一个ans=1。对于2,新建一个ans=2。对于3,右边有2了,就把3加入到2,ans=2。对于4,新建一个,ans=3。对于5加入到1和4都可以,对于6,加入到4和3都可以。这个可以使用并查集轻松实现。但是题目中的是有重复的。

      我们想,对于排好序的元素,每一个单调队列一定都是从中截取连续的一段作为自己的元素的,那么我们观察一下他的序号。例如样例,第一个队列中元素的序号为3 1 6,第二个为5 2 4。题目要求依次考虑,那么初始的元素必定序号最小,然后它左右两边的序号都要比它大,所以这是一个元素单调,元素的序号呈中间小,两边大的单调队列。特别的,序号递增或递减(左边没有元素或右边没有元素)。那么怎么求呢?

      第一种不重复元素的方法遇到重复的元素就没有办法了,但是发现了序号的规律之后,我们对于重复的元素,就可以合并了,然后记下相同元素所对应的序号最大与序号最小值即可。当前面一个元素(合并之后,元素是无相同的了)是递增的,那么当前这一个元素如果没有办法继续递增,就要新建一个单调队列了。前面元素递减同理。

      不存在一种情况使得相同的元素在不同的单调队列。因为队列起始元素自然递减更优,限制递减状态改为递增的是最小值,把相同元素放在不同的队列,并不能把最小的放过去,还不如放在一起。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define RG register
     8 #define LL long long
     9 #define fre(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout);
    10 using namespace std;
    11 const int MAXN=210000;
    12 int n,now,down,up,ans,top;
    13 int mx[MAXN],mi[MAXN];
    14 struct ed
    15 {
    16    int v,id;
    17 }a[MAXN];
    18 bool comp(ed x,ed y)
    19 {
    20    if(x.v!=y.v)
    21       return x.v<y.v;
    22    return x.id<y.id;
    23 }
    24 int main()
    25 {
    26    scanf("%d",&n);
    27    for(int i=1;i<=n;i++)
    28       {
    29          scanf("%d",&a[i].v);
    30          a[i].id=i;
    31       }
    32    sort(a+1,a+n+1,comp);
    33    top++; mi[top]=mx[top]=a[1].id;
    34    for(int i=2;i<=n;i++)
    35       {
    36          if(a[i].v!=a[i-1].v)
    37             top++ , mi[top]=a[i].id;
    38          if(a[i].v!=a[i+1].v)
    39             mx[top]=a[i].id;
    40       }
    41    now=mi[1]; down=1; up=0;
    42    for(int i=2;i<=top;i++)
    43       {
    44          if(up)//一个断点
    45             {
    46                if(mi[i]<now)
    47                   { ans++; up=0; down=1; now=mi[i]; }
    48                else
    49                   now=mx[i];
    50             }
    51          else if(down)
    52             {
    53                if(mx[i]<now)
    54                   now=mi[i];
    55                else
    56                   up=1,now=mx[i];
    57             }
    58       }
    59    printf("%d
    ",ans+1);
    60    return 0;
    61 }
  • 相关阅读:
    吐血巨献:VB网络编程(webbrowser+Inet+抓包封包+经验)
    亦思验证码识别系统3.1详解
    开机自动连接宽带程序
    轻松报选修智能报选修程序(适用于正方教学管理系统)
    低调发布一个百度谷歌关键字搜索工具
    解惑:Postmessage函数模拟鼠标单击指定坐标
    分享一些经典资源
    英文单词缩写查询
    css控制的个性导航栏
    导航栏中加入自动弹出下拉菜单
  • 原文地址:https://www.cnblogs.com/D-O-Time/p/7710677.html
Copyright © 2011-2022 走看看