【题解】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 }
个人博客地址: www.moyujiang.com 或 moyujiang.top