题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6602
题意
给出一个数组,问你最长的子区间,使得区间内的元素要么不出现,要么至少出现k次。
题解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
int t[N<<2],lz[N<<2];
int n,c,k;
void bd(int rt,int l,int r){
t[rt]=lz[rt]=0;
if(l==r) return;
int m=l+r>>1;
bd(rt<<1,l,m);
bd(rt<<1|1,m+1,r);
}
void pd(int rt){
if(lz[rt]){
t[rt<<1]+=lz[rt];
t[rt<<1|1]+=lz[rt];
lz[rt<<1]+=lz[rt];
lz[rt<<1|1]+=lz[rt];
lz[rt]=0;
}
}
void upd(int rt,int l,int r,int L,int R,int v){
if(R<L) return;
if(L<=l&&r<=R){
t[rt]+=v;
lz[rt]+=v;
return;
}
pd(rt);
int m=l+r>>1;
if(L<=m) upd(rt<<1,l,m,L,R,v);
if(m<R) upd(rt<<1|1,m+1,r,L,R,v);
t[rt]=max(t[rt<<1],t[rt<<1|1]);
}
int que(int rt,int l,int r,int x){
if(t[rt]<c) return n+1;
if(l==r) return l;
pd(rt);
int m=l+r>>1;
if(t[rt<<1]>=c) return que(rt<<1,l,m,x);
if(m<x&&t[rt<<1|1]>=c) return que(rt<<1|1,m+1,r,x);
return n+1;
}
int a[N];
queue<int>q[N];
int le[N],ri[N];
int num[N];
int main(){
while(scanf("%d%d%d",&n,&c,&k)!=EOF){
for(int i=1;i<=c;i++){
while(!q[i].empty()){
q[i].pop();
}
le[i]=1;
num[i]=0;
ri[i]=0;
}
bd(1,1,n);
int ans=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
q[a[i]].push(i);
upd(1,1,n,le[a[i]],i-1,-1);
upd(1,1,n,i,i,c-1);
le[a[i]]=i+1;
if(q[a[i]].size()>=k){
int tmp=q[a[i]].front();q[a[i]].pop();
upd(1,1,n,ri[a[i]]+1,tmp,1);
ri[a[i]]=tmp;
}
ans=max(ans,i-que(1,1,n,i)+1);
}
printf("%d\n",ans);
}
}