HDU-6602 Longest Subarray(2019杭電多校第二場1012)

題目鏈接
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

題意: 長度爲n的序列,求最大的子序列長度,要求子序列中所出現的數字個數>=k。
思路: 枚舉有邊界r,線段樹維護左邊界l的範圍。
對於每一個數a[r]來說,我們可以清楚的知道l的合法區間。離a[r]最近的一個數的位置爲P1,離r第k遠的數字位置P2,離r第k遠的數字位置P3,那麼,它的合法區間爲[P2,P3],[P1,r]。因此,我們可以對當前區間進行+1,最後查詢區間個數>=c的最左邊的邊界l即可。

#include<bits/stdc++.h>
using namespace std;
#define lson (rt<<1)
#define rson ((rt<<1)|1)
const int MAXN = 1e5+10;
int mx[MAXN<<2],lz[MAXN<<2];
vector<int>ve[MAXN];
int n,c,k;

void build(int rt,int L,int R)
{
    mx[rt] = lz[rt] = 0;
    if(L == R)  return ;
    int Mid = (L+R)>>1;
    build(lson,L,Mid);
    build(rson,Mid+1,R);
}

void down(int rt)
{
    if(!lz[rt]) return ;
    mx[lson] += lz[rt];
    mx[rson] += lz[rt];
    lz[lson] += lz[rt];
    lz[rson] += lz[rt];
    lz[rt] = 0;
}

void up(int rt)
{
    mx[rt] = max(mx[lson],mx[rson]);
}

void update(int rt,int L,int R,int l,int r,int x)
{
    if(l>r) return ;
    if(l<=L && R<=r){
        mx[rt] += x;
        lz[rt] += x;
        return ;
    }
    down(rt);
    int Mid = (L+R)>>1;
    if(l<=Mid)  update(lson,L,Mid,l,r,x);
    if(r > Mid) update(rson,Mid+1,R,l,r,x);
    up(rt);
}

int query(int rt,int L,int R,int l,int r)
{
    if(mx[rt]<c)    return 0;
    if(L == R)  return L;
    down(rt);
    int Mid = (L+R)>>1;
    if(mx[lson] >= c)   return query(lson,L,Mid,l,r);
    return query(rson,Mid+1,R,l,r);
}

int main()
{
    while(~scanf("%d%d%d",&n,&c,&k)){
        for(int i=1;i<=c;i++)   ve[i].clear(),ve[i].push_back(0);
        int ans = 0;
        build(1,1,n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            update(1,1,n,i,i,c-1);//對於除當前數之外,有C-1個數在當前位置沒有出現過
            update(1,1,n,ve[x].back()+1,i-1,-1);//上一次出現x的位置到當前位置中,在上行的update已經添加過,所以此時需要-1.
            ve[x].push_back(i);
            int t = ve[x].size() - k - 1;
            if(t >= 0)  update(1,1,n,ve[x][t]+1,ve[x][t+1],1);//在P2~P3的合法區間+1.
            int j = query(1,1,n,1,i);//查詢滿足要求的最左邊的左邊界L。
            if(!j)  continue;
            ans = max(ans,i-j+1);
        }
        cout<<ans<<endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章