核心:双指针
利用i、j维护一个区间,i是右端点,j是左端点。每次枚举区间的时候,会有重叠部分,重叠部分不需要重复计算id出现的次数。由于我们的cnt记录的是一个区间内,某个id出现的的次数。这个区间是动态的,因此,需要保证我们统计的cnt是我们当前枚举的这个区间的,所以这个区间以外的我们需要保持原样。每次枚举区间的时候,不重叠部分,需要进行cnt–的操作。这样我们在统计当前这个区间,某个id出现的次数是否大于k才能保证正确性。
注意这里的i、j并不是时间,而是我们存储ts和id的pair数组的下标。
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
typedef pair<int, int> pii;
int n,d,k;
pii s[N];
int cnt[N];
bool st[N];
int main(){
cin>>n>>d>>k;
for(int i=0;i<n;i++){
int a, b;
cin>>a>>b;
s[i]={a,b};
}
sort(s,s+n);//按时间进行排序
for(int i=0,j=0;i<n;i++){
int t=s[i].second;
cnt[t]++;
while(s[i].first-s[j].first>=d){
cnt[s[j].second]--;
j++;
}
if(cnt[t]>=k) st[t] = true;;
}
for (int i = 0; i <= 100000; i ++ ) if (st[i]) cout << i << endl;
return 0;
}