【题解】P3069 [USACO13JAN]牛的阵容Cow Lineup-C++

题目传送门

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

在任意一个符合条件的区间里,答案是区间内最多的那类牛的数量。

我们只需要从左到右扫描整个队列,找到每一个只含k+1种牛的区间(删除k种+保留的一种),取每个区间内数量最多牛的数量即可。

注意点: 血统编号在0-1,000,000,000之间,需要离散化。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 map<int,int> mp;
 4 int a[100010],lsh,cnt,l=1,r,c[100010],ans=-1;
 5 int main()
 6 {
 7     int n,k;
 8     cin>>n>>k;
 9     for(int i=1;i<=n;i++)
10     {
11         cin>>a[i];
12         if(!mp[a[i]])mp[a[i]]=++lsh;
13         a[i]=mp[a[i]]; 
14     }
15     while(r<=n)
16     {
17         r++;
18         if(!c[a[r]])cnt++;
19         c[a[r]]++;
20         while(cnt==k+2)
21         {
22             c[a[l]]--;
23             if(!c[a[l]])cnt--;
24             l++;
25         }
26         ans=max(c[a[r]],ans);
27     }
28     cout<<ans<<endl;
29     return 0;
30 } 

 

posted @ 2019-07-19 15:22  摸鱼酱  阅读(248)  评论(0编辑  收藏  举报