Longest Subarray HDU - 6602 線段樹+思維

You are given two integers C,KC,K and an array of NN integers a1,a2,...,aNa1,a2,...,aN. It is guaranteed that the value of aiai is between 11 to CC. 

We define that a continuous subsequence al,al+1,...,ar(l≤r)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∀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 KKtimes. 

You should find the longest good subarray and output its length. Or you should print 00 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)N,C,K(N,C,K≤105). 

The second line contains NN integer a1,a2,...,aN(1≤ai≤C)a1,a2,...,aN(1≤ai≤C). 

We guarantee that the sum of NNs, the sum of CCs and the sum of KKs in all test cases are all no larger than 5×1055×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

題意:給你一個長度爲n的序列,序列中的數的值在[1,c]之間,讓你求一個最長的子區間,這個區間中的值滿足:

[1,c]中間的所有數,要麼這個數出現0次,要麼這個數出現>=k次。輸出區間長度。

思路:由於區間不固定,我們可以考慮枚舉區間右端點。假設每個點有一個值maxx,這個值表示的是以這個值爲左端點的時候滿足條件的數的個數。

1.假設右端點現在是i,值爲a[i]。我們考慮區間[i,i],當k>1時,那麼這個區間滿足要求的數的個數maxx爲c-1,因爲只出現了一個數a[i],不滿足要求,而其餘c-1個數都沒出現,滿足要求,所以值maxx爲c-1。

2.假設右端點現在是i,值爲a[i],上一個出現val值的位置爲pos,那麼以i爲右端點,[pos+1,i-1]這個區間的任何一個位置作爲左端點時滿足條件的數應該-1,因爲在枚舉i這個位置之前,[pos+1,i-1]這個區間都視作沒有val這個值的,現在視作有,因此少了一個滿足條件的值,因此要maxx減一。

 3. 假設右端點現在是i,值爲a[i],如果val這個值加上這次已經出現了k次,假設從當前位置往左第k個值爲val的位置爲pos,第k個值爲val的位置爲pos1,那麼[pos1+1,pos]這個區間的任何一個位置作爲左端點時滿足條件的數應該+1,區間[pos1+1~pos,i)這個區間val這個值出現的次數爲k-1,並不符合要求。而區間[pos1+1~pos,i]這個區間val這個值出現的次數爲k,符合要求,因此要+1.

對於每一個右端點i,我們查詢區間[1,i]中離i點最遠的maxx的值爲c的位置pos,那麼區間長度爲i-pos+1。枚舉每個點做右端點,取可行區間長度的最大值即可。

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
int a[maxn],n,c,k,ans;
vector<int> v[maxn];
struct node{
	int l;
	int r;
	int ans;
	int laz;
	int maxx;
}tree[maxn<<2];
void pushup(int cur)
{
	tree[cur].maxx=max(tree[cur<<1].maxx,tree[cur<<1|1].maxx);
	if(tree[cur].maxx==tree[cur<<1].maxx) tree[cur].ans=tree[cur<<1].ans;
	else tree[cur].ans=tree[cur<<1|1].ans;
}
void pushdown(int cur)
{
	if(tree[cur].laz)
	{
		tree[cur<<1].maxx+=tree[cur].laz;
		tree[cur<<1].laz+=tree[cur].laz;
		tree[cur<<1|1].maxx+=tree[cur].laz;
		tree[cur<<1|1].laz+=tree[cur].laz;
		tree[cur].laz=0;	
	}
}
void build(int l,int r,int cur)
{
	tree[cur].l=l;
	tree[cur].r=r;
	tree[cur].ans=l;
	tree[cur].laz=0;
	tree[cur].maxx=0;
	if(l==r) return ;
	int m=(l+r)>>1;
	build(l,m,cur<<1);
	build(m+1,r,cur<<1|1);
}
void update(int L,int R,int val,int cur)
{
	if(L<=tree[cur].l&&tree[cur].r<=R)
	{
		tree[cur].maxx+=val;
		tree[cur].laz+=val;
		return ;
	}
	pushdown(cur);
	if(L<=tree[cur<<1].r) update(L,R,val,cur<<1);
	if(R>tree[cur<<1].r) update(L,R,val,cur<<1|1);
	pushup(cur);
}
int query(int L,int R,int cur)
{
	if(tree[cur].maxx!=c) return -1;
	if(L<=tree[cur].l&&tree[cur].r<=R) return tree[cur].ans;
	pushdown(cur);
	int res=-1;
	if(L<=tree[cur<<1].r) res=query(L,R,cur<<1);
	if(R>tree[cur<<1].r&&res==-1) res=query(L,R,cur<<1|1);
	return res;
}
int main()
{
	while(~scanf("%d%d%d",&n,&c,&k))
	{
		ans=0;
		for(int i=1;i<=c;i++)
		{
			v[i].clear();
			v[i].push_back(0);
		}
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		build(1,n,1);
		for(int i=1;i<=n;i++)
		{
			update(i,i,c-1,1);
			if(v[a[i]].back()+1<=i-1) update(v[a[i]].back()+1,i-1,-1,1);
			v[a[i]].push_back(i);
			if(v[a[i]].size()>k)
			{
				int pos=v[a[i]].size()-k;
				update(v[a[i]][pos-1]+1,v[a[i]][pos],1,1);
			}
			int L=query(1,i,1);
			if(L==-1) continue;
			ans=max(ans,i-L+1);
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章