终于到了一年一度的NOIP比赛了,多么令人期待和兴奋的一天!其实,人们最高兴的还不是遇见老朋友,而是结交新朋友。可是结交新的朋友就需要很多时间,而除了考试之外时间并不多。例如小L,他在NOIP的入口处等待开门时,决定趁机和其它市县的牛们多套近乎。可是队伍太长,且人们都很自觉的站成仅仅一列,而小L又很想多交不同地方的朋友,因此小L想知道他在哪一个区域内可以结交到最多的不同地方的朋友。当然,这个区域不能太大,否则还没考试他就累死了。
现在有n个人,题目给出了他们每个人所在市县的编号。他们站在一个从左向右的队伍中。小L不在队列中。他想找到一个长度不超过D的区域,使他能够找到最多的不同地方的朋友。要求输出能找到的朋友所在不同市县的最大数和找到这些朋友的最小区间长度。比如在整个队伍内他按从左向右顺序找到了3个A地朋友,1个B地朋友,1个C地朋友。假设D=5,那么不同市县的最大数为3(A地、B地、C地),最小区间长度为3(只须结交A地的最右面的一个人即可得到最大市县数3,因此区间长度不是5而是3)。假设在队伍内的人他都还没有结交。
输入
第一行为两个正整数n,D。分别表示队伍人数和他想找到的最长的区间长度。
接下来的n行,每行有一个整数,表示每个人所在市县的编号(从左向右)。
输出
输出数据为一行,这行有两个整数,用空格分开,按顺序分别代表能找到的朋友所在不同市县的最大数和找到这些朋友的最小区间长度。
样例输入
5 4
1
1
1
2
3
样例输出
3 3
提示
对于 100% 的数据,保证5<=n<=1000000, 1<=D<=n, 所有市县编号不超过32767。
#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
typedef long long ll;
deque<ll> lis;//选用deque,可同时对头和尾进行修改
ll n,d,r;
ll flag[32800];//统计容器对应元素的个数
ll flag1[32800];//找到一区段后统计该区段内个元素对应个数;也可不定义,清空flag[]即可
//在此题中数据不超过32767,可用桶排思想记录个数
ll st[1000010];//存放所有数据
ll num,lenth,lenth1,ans,ans1;
ll read() {//快读
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int main() {
n=read();
d=read();
for(ll i=1; i<=n; i++) st[i]=read();
for(ll i=1; i<=n; i++) {
num=st[i];
if(lenth1==0) {//容器为空,不必考虑重复元素
ans1++;
lenth1++;
flag[num]++;
lis.push_back(num);
}
else {
ll ls=lis.front();
if(lenth1<d) {//容器未满,只需将元素添至容器尾,判断当前加入元素是否重复
flag[num]++;
lenth1++;
lis.push_back(num);
if(flag[num]==1) ans1++;
}
else {//容器满,考虑头的删除,尾的加入;删除和加入可能影响元素种类
flag[ls]--;
if(flag[ls]==0) ans1--;
lis.pop_front();
lis.push_back(num);
flag[num]++;
if(flag[num]==1) ans1++;
}
}
if(ans<ans1) {//最大种类值,保存右坐标和长度
ans=ans1;
lenth=lenth1;
r=i;
}
}
lis.clear();//已寻得最大种类,清空容器
for(int i=r,len=lenth1; len>0; i--,len--) {
lis.push_back(st[i]);
flag1[st[i]]++;
}
//将目标区域段元素存入容器;正反向无妨;即亦可于上段中保存左值
while(flag1[lis.front()]>1) {
flag1[lis.front()]--;
lis.pop_front();
lenth--;
}
while(flag1[lis.back()]>1) {
flag1[lis.back()]--;
lis.pop_back();
lenth--;
}
//左右双向删减
cout<<ans<<' '<<lenth;
return 0;
}