CodeForces 190D. Non-Secret Cypher(思维)
题目链接
题意:给出n个元素的数列(n<=4e5),问有多少个子区间满足至少有一个数值出现至少K次。
解析:
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define pll pair<ll,ll>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
#define rson rt<<1|1,m+1,r
#define lson rt<<1,l,m
#define mod 323232323
using namespace std;
const int N=4e5+100;
int arr[N];
/*
枚举到i
设已经出现arr[i]的个数为num
那么已经出现k次并且左端点最靠右的数字的
左端点位置+1之前的位置
到当前位置的区间都会加1
如果num>=k
那么从这个数字第num-k+2个位置之前的所有位置
到当前位置的区间都会加1
考虑到有重复的情况
我们取这两个位置最大值即可
所以我们可以设定一个最大值r
如果出现》=k的情况就取最大值即可
*/
int main()
{
#ifdef LOCAL_DEFINE
freopen("D:\\rush.txt","r",stdin);
#endif
ios::sync_with_stdio(false),cin.tie(0);
ll n,k,r=0,a;
ll sum=0;
cin>>n>>k;
map<ll,ll>pre;
map<ll,ll>next;
map<ll,ll>lmp;
map<ll,ll>mp;
rep(i,1,n)
{
cin>>a;
if(pre[a]!=0)
next[pre[a]]=i;
pre[a]=i;
if(lmp[a]==0)
lmp[a]=i;
mp[a]++;
if(mp[a]==k)
{
r=max(r,lmp[a]);
}
else if(mp[a]>k)
{
lmp[a]=next[lmp[a]];
r=max(r,lmp[a]);
}
sum+=r;
}
cout<<sum<<endl;
}