zoukankan      html  css  js  c++  java
  • bzoj 2457 [BeiJing2011]双端队列 模拟+贪心

     [BeiJing2011]双端队列

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 457  Solved: 203
    [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。

    题解:第一思路很重要:我们将原序列中的所有数排序,然后从小到大一个个扔回原序列中。根据贪心的思想,我们一定是先连续扔一些个,再将这几个放到一个队列中,再连续的扔一些个。。。并且我们每一次扔的数一定是越多越好。

    那么我们只需要知道每次扔进去的数需要满足什么条件即可。根据题意,如果令pi表示第i大的数的位置,那么每次扔进去的pi一定是先递减再递增的。所以我们将所有相同的数合并,得到每个数出现的最左边和最右边的位置,然后模拟一发就行了。

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<queue>
     7 
     8 #define N 200007
     9 using namespace std;
    10 inline int read()
    11 {
    12     int x=0,f=1;char ch=getchar();
    13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 
    18 int n,m,tag,pre,ans;
    19 int p[N],v[N],sm[N],sn[N];
    20 
    21 
    22 bool cmp(int a,int b)
    23 {
    24     return (v[a]==v[b])?(a<b):(v[a]<v[b]);
    25 }
    26 int main()
    27 {
    28     n=read();
    29     for(int i=1;i<=n;i++)
    30         v[i]=read(),p[i]=i;v[0]=-1;
    31     sort(p+1,p+n+1,cmp);
    32     for(int i=1;i<=n;i++)
    33     {
    34         if(v[p[i]]!=v[p[i-1]]) m++,sm[m]=sn[m]=p[i];
    35         sm[m]=max(sm[m],p[i]),sn[m]=min(sn[m],p[i]);
    36     }
    37     for(int i=1;i<=m;i++)
    38     {
    39         if(i==1||(tag&&sn[i]<pre)) ans++,tag=0,pre=sn[i];
    40         else if(!tag&&sm[i]>pre) tag=1,pre=sm[i];
    41         else if(!tag&&sm[i]<pre) pre=sn[i];
    42         else if(tag&&sn[i]>pre) pre=sm[i];
    43     }
    44     printf("%d",ans);
    45 }
     
  • 相关阅读:
    ubuntu下文件安装与卸载
    webkit中的JavaScriptCore部分
    ubuntu 显示文件夹中的隐藏文件
    C语言中的fscanf函数
    test
    Use SandCastle to generate help document automatically.
    XElement Getting OuterXML and InnerXML
    XUACompatible meta 用法
    Adobe Dreamweaver CS5.5 中文版 下载 注册码
    The Difference Between jQuery’s .bind(), .live(), and .delegate()
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8847750.html
Copyright © 2011-2022 走看看