J. LRU
分析:
-
二分答案 + + + m a p map map a n d and and s e t set set a n d and and q u e u e queue queue 乱搞
-
让我们求最小的满足条件的缓存容积(为了方便,下文用长度表示),可以想到用二分
-
主要的麻烦点在于判断当前二分的长度 ( d ) (d) (d) 是否成立
要维护长度始终小于等于 d d d,然后 d d d 个元素又互不相同,可以用 s e t + q u e u e set+queue set+queue 来维护:
最后一个难想的点就是结束出队的条件(详见代码)
-
为什么想到用队列维护:离得最远的抛弃,就是先进先出啊
-
s e t set set 维护的就是一个集合:包含 d d d 个互不相同的元素
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
map <int,int> ma,mp;
set <int> se;
int a[N];
bool check(int d,int n,int k)
{
int tot=0;
queue <int> q;
mp.clear();
se.clear();
for(int i=1;i<=n;i++)
{
q.push(a[i]); //全部入队
if(mp[a[i]])
{
tot++;
mp[a[i]]++;
}
else
{
mp[a[i]]=1;
if(se.size()<d) se.insert(a[i]);
else
{
while(!q.empty())
{
int u=q.front();
q.pop();
mp[u]--;
if(mp[u]==0) // 当某一个元素在队列当中不存在了,它才是我们要在set当中去除的元素
{
se.erase(u);
break;
}
}
}
se.insert(a[i]); // 别忘了将当前元素入set
}
}
return tot>=k;
}
signed main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
ma[a[i]]++;
}
int cnt=0;
// 计算所有可能的 hit
for(int i=1;i<=n;i++)
{
if(ma[a[i]]>1)
{
cnt+=ma[a[i]]-1;
ma[a[i]]=0;
}
}
if(cnt<k)
{
cout<<"cbddl"<<endl;
return 0;
}
int l=1,r=n,ans=0;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid,n,k))
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
cout<<ans<<endl;
}