洛 谷 P 3069 [ U S A C O 13 J A N ] 牛 的 阵 容 C o w L i n e u p \color{#00F}{洛谷\ P3069\ [USACO13JAN]牛的阵容Cow Lineup} 洛谷 P3069 [USACO13JAN]牛的阵容CowLineup
T i m e L i m i t : 2000 M S \color{green}{Time Limit: 2000 MS} TimeLimit:2000MS
M e m o r y L i m i t : 125.98 M B \color{green}{Memory Limit: 125.98MB} MemoryLimit:125.98MB
P r o b l e m D e s c r i p t i o n \color{blue}{Problem\ Description} Problem Description
Farmer John’s N cows (1 <= N <= 100,000) are lined up in a row. Each cow is identified by an integer “breed ID” in the range 0…1,000,000,000; the breed ID of the ith cow in the lineup is B(i). Multiple cows can share the same breed ID.
FJ thinks that his line of cows will look much more impressive if there is a large contiguous block of cows that all have the same breed ID. In order to create such a block, FJ chooses up to K breed IDs and removes from his lineup all the cows having those IDs. Please help FJ figure out the length of the largest consecutive block of cows with the same breed ID that he can create by doing this.
I n p u t \color{blue}{Input} Input
Line 1: Two space-separated integers: N and K.
Lines 2…1+N: Line i+1 contains the breed ID B(i).
O u t p u t \color{blue}{Output} Output
S a m p l e I n p u t \color{blue}{Sample\ Input} Sample Input
9 1
2
7
3
7
7
3
7
5
7
S a m p l e O u t p u t \color{blue}{Sample \ Output} Sample Output
4
E x p l a n a t i o n \color{blue}{Explanation} Explanation
There are 9 cows in the lineup, with breed IDs 2, 7, 3, 7, 7, 3, 7, 5, 7. FJ would like to remove up to 1 breed ID from this lineup.
By removing all cows with breed ID 3, the lineup reduces to 2, 7, 7, 7, 7, 5, 7. In this new lineup, there is a contiguous block of 4 cows with the same breed ID (7).
牛的编号很大,首先离散化。
对于每一头牛,我们考虑以它作为最后一个产生的最大答案是多少。
显然,如果相同两点之间有多于k个元素那么他们不可能相连。
那么,我们可以考虑尺取法。
考虑维护当前可以取得到的左端点 l l l
维护当前的牛的编号数量 t y p e type type
维护当前编号为 i i i 的牛的数量 c n t [ i ] cnt[i] cnt[i]
当前第 i i i头牛加入时,如果当前牛的颜色数量 t y p e type type达到 k + 2 k+2 k+2
就将左端点的牛 l l l删除
每一次都有 a n s = m a x ( a n s , c n t [ a [ i ] ] ) ans=max(ans,cnt[a[i]]) ans=max(ans,cnt[a[i]])
因为左端点一定只会从左往右经过一次,每一头牛也只会被加入和删除一次
总复杂度 O ( n ) O(n) O(n)
代码实现如下:
#include
using namespace std;
const int MAXN=100005;
int n,k,tot=0,type=0,ans=0;
int a[MAXN],cnt[MAXN];
map <int,int> id;
inline int read()
{
int X=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+(ch^'0'); ch=getchar();}
return X*f;
}
int main()
{
freopen("input.txt","r",stdin);
n=read(); k=read();
for(int i=1;i<=n;++i)
{
a[i]=read();
if(!id[a[i]]) id[a[i]]=++tot;
a[i]=id[a[i]];
}
int l=1,r=0;
while(r<n)
{
++r;
if(!cnt[a[r]]) ++type;
++cnt[a[r]];
while(type==k+2)
{
--cnt[a[l]];
if(!cnt[a[l]]) --type;
++l;
}
ans=max(ans,cnt[a[r]]);
}
printf("%d",ans);
return 0;
}