题目描述:
𝑅𝑒𝑘𝑖是一名狙击手,凭借肉眼视觉可以做到精确命中绝对半径2051公尺的一切目标。
作为一名优秀的狙击手,𝑅𝑒𝑘𝑖不仅经常保养枪支,也经常保养弹药。
𝑅𝑒𝑘𝑖有𝑛枚子弹,第𝑖枚的型号为𝐶𝑖,𝑅𝑒𝑘𝑖打算扔掉其中最多𝑘枚。
大多数优秀的狙击手都有艺术癖好,𝑅𝑒𝑘𝑖希望扔掉一部分子弹后,最
长的连续相同子弹序列的长度尽量长。
输入格式:
第一行,两个整数𝑛,𝑘。0<=n,k<=1e5
第二行,𝑛个正整数𝐶𝑖。1<=Ci<=1e9
输出格式:
一行,一个整数,最长的连续相同子弹序列的长度。
解题报告:
首先离散化 O(nlogn)
在用vector依次记录每种出现的位置,很明显答案的区间具有单调性,故可用二分来做,以vector记录位置为右端点,二分左端点即可。
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
const int MOD=998244353;
const double PI=acos(-1);
const double e=2.718281828459;
pii p[maxn];
int d[maxn];
vector<int>v[maxn];
bool cmp(pii a,pii b)
{
if(a.f==b.f){return a.s<b.s;}
return a.f<b.f;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&p[i].f);
d[i]=p[i].f;
p[i].s=i;
}
sort(p+1,p+n+1,cmp);
int id=1;
d[p[1].s]=id;
for(int i=2;i<=n;i++){
if(p[i].f==p[i-1].f){
d[p[i].s]=id;
}
else{
d[p[i].s]=++id;
}
}
for(int i=1;i<=n;i++){
v[d[i]].pb(i);
}
int mx=-1;
for(int i=1;i<=id;i++){
for(int j=0;j<v[i].size();j++){
int l=0,r=j,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(v[i][j]-v[i][mid]+1<=(j-mid+1)+m){
ans=mid;r=mid-1;
}
else{
l=mid+1;
}
}
mx=max(mx,j-ans+1);
}
}
printf("%d\n",mx);
return 0;
}