思路:大水题
找出一个区间,满足区间尽可能长,且科目数为k+1
则可删除k个科目,剩下一个人数最多的科目,形成连续子序列
显而易见,用线段树维护,因为我只会线段树
实现方法:
暴力枚举head,tail区间
用线段树维护科目数和最大科目人数
先删除原先的
假如区间的科目数<=K+1则插入
然后ANS=max(C[1]);
CODE
#include<iostream> #include<cstdio> #include<map> using namespace std; map<int,int>to; int a[1000005],n,m,c[1000005],head,tail,tot,ans,num[1000005]; void del(int l,int r,int k,int x) { if(l==r) { c[k]--; if(c[k]==0)num[k]=0; } else { int mid=(l+r)/2; if(x<=mid) { del(l,mid,k*2,x); } else { del(mid+1,r,k*2+1,x); } c[k]=max(c[k*2],c[k*2+1]); num[k]=num[k*2]+num[k*2+1]; } } void ins(int l,int r,int k,int x) { if(l==r) { c[k]++; num[k]=1; } else { int mid=(l+r)/2; if(x<=mid) { ins(l,mid,k*2,x); } else { ins(mid+1,r,k*2+1,x); } c[k]=max(c[k*2],c[k*2+1]); num[k]=num[k*2]+num[k*2+1]; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(to[a[i]]==0)to[a[i]]=++tot; } head=0;tail=1; ins(1,tot,1,to[a[1]]); while(head<tail) { head++; if(head>1)del(1,tot,1,to[a[head-1]]); while(num[1]<=m+1&&tail<n) { ins(1,tot,1,to[a[++tail]]); } if(num[1]>m+1)del(1,tot,1,to[a[tail--]]); if(tail<=n) { ans=max(ans,c[1]); } } printf("%d",ans); }