• 【题解】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
  • 相关阅读:
    jmeter根据负载量计算并发用户数实例
    学生指导——德育
    命令行模式(非GUI模式)下执行jmeter,生成HTML性能测试报告,自定义线程数;
    jmeter 测试某系统5分钟内能完成5000笔查询业务,且90%的响应时间不超过3s,并求出需要设置的线程数
    jmeter 测试某网页最大并发用户数;
    ZOJ 3213
    POJ 2411 插头DP
    滑雪(ski)
    Puzzles
    Lorenzo Von Matterhorn
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11213468.html
Copyright © 2020-2023  润新知