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 }
     
  • 相关阅读:
    Blazor 服务端组件 Render, RenderFragment ,RenderTreeBuilder, CascadingValue/CascadingParameter
    Git Submodule管理项目子模块
    使用Try.NET创建可交互.NET文档
    开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor
    搞懂Xamarin.Forms布局,看这篇应该就够了吧
    【译】.NET 跨平台界面框架和为什么你首先要考虑再三
    Roslyn 语法树中的各种语法节点及每个节点的含义
    数组的子集
    查找字符串中的最长无重复字符的子串
    双通道无限蓝屏
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8847750.html
Copyright © 2011-2022 走看看