1012 Longest Subarray
Longest Subarray
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 873 Accepted Submission(s): 265
Problem Description
You are given two integers C,K and an array of N integers a1,a2,…,aN. It is guaranteed that the value of ai is between 1 to C.
We define that a continuous subsequence al,al+1,…,ar(l≤r) of array a is a good subarray if and only if the following condition is met:
∀x∈[1,C],∑i=lr[ai=x]=0or∑i=lr[ai=x]≥K
It implies that if a number appears in the subarray, it will appear no less than K times.
You should find the longest good subarray and output its length. Or you should print 0 if you cannot find any.
Input
There are multiple test cases.
Each case starts with a line containing three positive integers N,C,K(N,C,K≤105).
The second line contains N integer a1,a2,…,aN(1≤ai≤C).
We guarantee that the sum of Ns, the sum of Cs and the sum of Ks in all test cases are all no larger than 5×105.
Output
For each test case, output one line containing an integer denoting the length of the longest good subarray.
Sample Input
7 4 2
2 1 4 1 4 3 2
Sample Output
4
Source
2019 Multi-University Training Contest 2
题意:给一个序列,求一个最长的子串满足:每种出现的数字的个数>=k
题解:固定右端点,那么左端点合法的范围应该是一个区间[1,x],其中x是在右端点左侧并且距离右端点第k近的和右端点值一样的数字的位置,同时固定右端点之后,不取右端点值的右侧合法的范围应该是在[y,z],其中y是右端点右侧并且距离右端点最近的和右端点值一样的数字的位置,问题即转化为区间覆盖问题,固定右端点同时更新区间覆盖,通过寻找被覆盖次数=c的最小下标i作为左端点完成对答案的更新
#include
using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<
const int maxn=3e5+5;
vector<int>pos[maxn];
int now[maxn],a[maxn];
int n,c,k;
struct node{
int l;
int r;
int maxx;
int lazy;
}nod[maxn<<2];
void pushup(int rt){
nod[rt].maxx=max(nod[rt<<1].maxx,nod[(rt<<1)|1].maxx);
}
void build(int l,int r,int rt){
nod[rt].l=l;
nod[rt].r=r;
nod[rt].maxx=0;
nod[rt].lazy=0;
if(l==r){
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,(rt<<1)|1);
pushup(rt);
}
void pushdown(int rt){
if(nod[rt].lazy){
nod[rt<<1].maxx+=nod[rt].lazy;
nod[(rt<<1)|1].maxx+=nod[rt].lazy;
nod[rt<<1].lazy+=nod[rt].lazy;
nod[(rt<<1)|1].lazy+=nod[rt].lazy;
nod[rt].lazy=0;
}
}
void update(int l,int r,int L,int R,int rt,int val){
if(L>R)return;
if(l>=L&&r<=R){
nod[rt].maxx+=val;
nod[rt].lazy+=val;
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(mid>=L)update(l,mid,L,R,rt<<1,val);
if(mid<R)update(mid+1,r,L,R,(rt<<1)|1,val);
pushup(rt);
}
int query(int l,int r,int rt){
if(l==r){
if(nod[rt].maxx==c)
return l;
else
return -1;
}
pushdown(rt);
int mid=(l+r)>>1;
if(nod[rt<<1].maxx==c){
return query(l,mid,rt<<1);
}
else if(nod[(rt<<1)|1].maxx==c){
return query(mid+1,r,(rt<<1)|1);
}
return -1;
}
int main(){
while(scanf("%d%d%d",&n,&c,&k)==3){
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,n,1);
for(int i=1;i<=c;i++){
pos[i].clear();
pos[i].push_back(0);
now[i]=0;
}
for(int i=1;i<=n;i++){
pos[a[i]].push_back(i);
}
for(int i=1;i<=c;i++){
pos[i].push_back(n+1);
update(1,n,pos[i][0]+1,pos[i][1]-1,1,1);
}
int ans=0;
for(int i=1;i<=n;i++){
int xx=a[i];
update(1,n,pos[xx][now[xx]]+1,pos[xx][now[xx]+1]-1,1,-1);
if(now[xx]>=k)update(1,n,1,pos[xx][now[xx]-k+1],1,-1);
now[xx]++;
update(1,n,pos[xx][now[xx]]+1,pos[xx][now[xx]+1]-1,1,1);
if(now[xx]>=k)update(1,n,1,pos[xx][now[xx]-k+1],1,1);
int ac=query(1,n,1);
if(ac==-1)continue;
ans=max(ans,i-ac+1);
}
printf("%d\n",ans);
}
return 0;
}