#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <queue>
#include <cstring>
#include <stack>
#define lson rt<<1
#define rson rt<<1|1
const static int maxn = 1e5+10;
using namespace std;
typedef long long ll;
int n, c, k;
struct segmenttree
{
ll mx;
ll mark;
}st[maxn<<2];
vector <int> pos[maxn];
int a[maxn];
void pushup(int rt)
{
st[rt].mx = max(st[lson].mx, st[rson].mx);
}
void pushdown(int rt)
{
if(st[rt].mark != 0)
{
st[lson].mark = st[rson].mark = st[rt].mark;
st[lson].mx += st[lson].mark;
st[rson].mx += st[rson].mark;
st[rt].mark = 0;
}
}
void buildtree(int l, int r, int rt)
{
st[rt].mark = 0;
if(l == r)
{
st[rt].mx = 0;
return;
}
int m = (l + r) >> 1;
buildtree(l, m, lson);
buildtree(m+1, r, rson);
pushup(rt);
}
void update(int _l, int _r, int l, int r, int rt, int val)
{
if(_l > _r)
return;
//cout<<_l<<" "<<_r<<" "<<l<<" "<<r<<" "<<rt<<endl;
if(_l <= l && _r >= r)
{
st[rt].mx += val;
//cout<<l<<" "<<r<<endl;
st[rt].mark += val; // 这里要用加的
return;
}
pushdown(rt);
int m = (l + r) >> 1;
if(_l <= m)
update(_l, _r, l, m, lson, val);
if(_r > m)
update(_l, _r, m+1, r, rson, val);
pushup(rt);
}
int query(int l, int r, int rt)
{
if(l == r)
return l;
pushdown(rt);
int ans = -1;
int m = (l + r) >> 1;
if(st[lson].mx == c)
ans = query(l, m, lson);
else if(st[rson].mx == c)
ans = query(m+1, r, rson);
return ans;
}
int num[maxn];
int main()
{
while(scanf("%d %d %d", &n, &c, &k) != EOF)
{
memset(num, 0, sizeof num);
for(int i=1; i<=c; i++)
{
pos[i].clear();
pos[i].push_back(0);
}
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
pos[a[i]].push_back(i);
}
buildtree(1, n, 1);
for(int i=1; i<=c; i++)
{
pos[i].push_back(n+1);
//cout<<pos[i][1]<<endl;
update(1, pos[i][1]-1, 1, n, 1, 1);
num[i] = 0;
}
int ans = 0;
for(int i=1; i<=n; i++)
{
int t = a[i];
update(pos[t][num[t]]+1, pos[t][num[t]+1]-1, 1, n, 1, -1);//这样写起来思路清晰,去掉已经不满足的区间,再加上新满足的区间,
//由于log实现,所以我们可以尽量用线段树的相关操作,避免出错。
if(num[t] >= k)
update(1, pos[t][num[t]-k+1], 1, n, 1, -1);
num[t]++;
update(pos[t][num[t]]+1, pos[t][num[t]+1]-1, 1, n, 1, 1);
if(num[t] >= k)
update(1, pos[t][num[t]-k+1], 1, n, 1, 1);
int temp = query(1, n ,1);
if(temp != -1)
ans = max(ans, i-temp+1);
}
printf("%d\n", ans);
}
return 0;
}
/*
7 4 2
2 1 4 1 4 3 2
*/
挖坑
做这道题体会太多,现在还太菜了,不能讲的很好,日后补上,只能说东西不能学死,像线段树这种东西,只能作为一种思想去学,不能认为会线段树就能解决线段树相关的东西,真正会灵活应用才是真正学会了。