zoukankan      html  css  js  c++  java
  • 【题解】P1638 逛画展-C++

    原题传送门

    思路
    这道题目可以通过尺取法来完成 (我才不管什么必须用队列)
    什么是尺取法呢?
    顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。
    之所以需要掌握这个技巧,是因为尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以尺取法是一种高效的枚举区间的方法,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,无法得出正确答案。

    首先这是尺取法的板子题,我们假设从第s幅画开始看,为了覆盖所有大师的画需要看到t。这样的话可以知道如果从s+1开始看的话,那么必须看到t>=t幅画为止。so,我们从区间的最开头把s取出之后,s这幅画所属的大师出现次数就要减1,如果此时这个大师出现次数为0了,在同一个大师再次出现之前,不停将区间末尾t向后推进即可。每次在区间末尾追加画t时将t所属的大师出现次数加1,这样就完成了下一个区间上各个大师出现次数的更新,重复这一操作便能在O(nlogn)的时间复杂度下解决这道题。
    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int p[1000010],k[2019];
     4 set<int> s;int n,m;
     5 int main()
     6 {
     7     cin>>n>>m;
     8     int l=1,r=n,cnt=0,left=1,right=n;
     9     for(int i=1;i<=n;i++)
    10     {
    11         cin>>p[i];
    12         k[p[i]]++;
    13         if(!s.count(p[i]))cnt++;
    14         s.insert(p[i]);
    15         if(cnt==m)
    16         {
    17             r=i;
    18             while(k[p[l]]>1)
    19             {
    20                 k[p[l]]--;
    21                 l++;
    22             }
    23             if(r-l<right-left)left=l,right=r;
    24         }
    25     }
    26     cout<<left<<" "<<right<<endl;
    27     return 0;
    28  } 
    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    ubuntu 编译安装 bochs2.4.6
    Android和QtExtended在设计方法上的共通之处
    MySQL C API programming tutorial
    linux书籍
    登陆、非登陆shell,交互、非交互shell,以及它们的startup文件
    CSS中的margin属性
    如何比较两个内容相似的Word文档
    汇编语言基础之三 变量的访问和流程控制指令
    [转]80X86 汇编指令符号大全(A~Z)
    找不到VS2008中三个新的样式窗口
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11213468.html
Copyright © 2011-2022 走看看