HDU 6602 Longest Subarray (线段树)

题意:

1e5的数组,c(1e5)种数字求最长的子串,使得其中每个出现的数字出现的次数为0次或者大于k次

思路:

枚举右端点i,维护当前右端点时,每个左端点的可行元素数量,当且仅当可行元素为c时更新答案

每次用最左边的可行的左端点与当前右端点更新答案

对于每个元素,如果它从i往左第1次出现的元素为pos1,第k次出现的为pos2

那么该元素的可行区域为[1,pos2]与[pos1+1,i]

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>

#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 2e5+100;
const int maxm = 4e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);


int n,c,k;
int a[maxn];
vector<int>v[maxn];
int mx[maxn<<2];
int addv[maxn<<2];
void build(int l, int r, int root){
    int mid = (l+r)>>1;
    if(l==r){mx[root]=c;return;}
    build(lson);
    build(rson);
    mx[root]=max(mx[lc],mx[rc]);
    addv[root]=0;
    return;
}
void pushdown(int l, int r, int root){
    if(addv[root]){
        addv[lc]+=addv[root];
        addv[rc]+=addv[root];
        mx[lc]+=addv[root];
        mx[rc]+=addv[root];
        addv[root]=0;
    }
    return;
}
void update(int x, int y, int val, int l, int r, int root){
    int mid = (l+r)>>1;
    if(x<=l&&r<=y){
        addv[root]+=val;
        mx[root]+=val;
        return;
    }
    pushdown(l,r,root);
    if(x<=mid)update(x,y,val,lson);
    if(y>mid)update(x,y,val,rson);
    mx[root]=max(mx[rc],mx[lc]);
    return;
}
int ask(int l, int r, int root){
    int mid = (l+r)>>1;
    if(l==r){
        if(mx[root]==c)return l;
        else return inf;
    }
    pushdown(l,r,root);
    if(mx[lc]==c)return ask(lson);
    else if(mx[rc]==c)return ask(rson);
    return inf;
}


int main(){
    while(~scanf("%d %d %d", &n, &c, &k)){
        for(int i = 1; i <= n; i++){v[i].clear();v[i].pb(0);}
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        build(1,n,1);
        int ans = 0;
        for(int i = 1; i <= n; i++){
            if((int)v[a[i]].size()>k){
                int l = v[a[i]][v[a[i]].size()-k];
                int r = v[a[i]].back();
                update(l+1,r,1,1,n,1);
                v[a[i]].pb(i);
                l=v[a[i]][v[a[i]].size()-k];
                r=v[a[i]].back();
                update(l+1,r,-1,1,n,1);
            }
            else{
                update(v[a[i]].back()+1,i,-1,1,n,1);
                v[a[i]].pb(i);
                if((int)v[a[i]].size()>k){
                    int l = v[a[i]][v[a[i]].size()-k];
                    update(1,l,1,1,n,1);
                }
            }
            int L = ask(1,n,1);
            ans=max(ans,max(0,i-L+1));
        }
        printf("%d\n",ans);
    }
    return 0;
}
/*
7 5 2
3 1 5 2 5 2 3


 */

 

posted @ 2019-08-01 21:13  wrjlinkkkkkk  阅读(367)  评论(0编辑  收藏  举报