hdu6602---線段樹

Longest Subarray

題意:一個數列,每一個元素大小都在1到C之間,求一個最長的子串,知足在這個子串中1到C之間的每一個數字要麼出現0次,要麼出現至少K次。php

題解:\(i\)從1到n枚舉右端點,維護一個\(tree[j]\)表示在\(i\)爲右端點時以\(j\)爲左端點可行的個數(這裏的可行是指對於1到C之間的某一個數是否可行,即\(j\)\(i\)之間\(X\)的個數是否知足題意,\(X\epsilon(1,C)\))。那麼對於固定的\(i\)顯然當\(tree[j]==C\)\([j,i]\)是一個可行區間,找出最小的\(j\)便可. 上述操做在線段樹上維護.c++

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,c,k,a[100005];
int tree[maxn*4],tag[maxn*4];
inline int ls(int x){
    return x<<1;
}
inline int rs(int x){
    return x<<1|1;
}
void change(int root,int del){
    tree[root]+=del;
    tag[root]+=del;
}
void pushdown(int root,int l,int r){
    if(!tag[root]) return;
    int mid=(l+r)>>1;
    change(ls(root),tag[root]);
    change(rs(root),tag[root]);
    tag[root]=0;
}
void update(int root,int l,int r,int il,int ir,int del){
    if(r<il||l>ir) return;
    if(l>=il&&r<=ir) {
        tree[root] += del;
        tag[root] += del;
        return;
    }
    pushdown(root,l,r);
    int mid=(l+r)>>1;
    update(ls(root),l,mid,il,ir,del);
    update(rs(root),mid+1,r,il,ir,del);
    tree[root]=max(tree[ls(root)],tree[rs(root)]);
}
int ask(int root,int l,int r,int il,int ir){
    if(r<il||l>ir) return -1;
    if(tree[root]<c) return -1;
    if(l==r) return l;
    pushdown(root,l,r);
    int mid=(l+r)>>1;
    int tmp=ask(ls(root),l,mid,il,ir);
    if(tmp>0) return tmp;
    return ask(rs(root),mid+1,r,il,ir);
}
vector<int> pos[maxn];
int main(){
    while(~scanf("%d%d%d",&n,&c,&k)) {
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=c;i++) {
            pos[i].clear();
        }
        if(k==1){
            printf("%d\n",n); continue;
        }
        int nn=n*4;
        for(int i=1;i<=nn;i++) tree[i]=0,tag[i]=0;
        int ans=0;
        for(int i=1;i<=n;i++){
            pos[a[i]].push_back(i);
            update(1,1,n,i,i,c-1);
            int siz=pos[a[i]].size();
            if(siz>=1){
                int l=siz-2,r=siz-1;
                if(l<0) l=1;
                else l=pos[a[i]][l]+1;
                r=pos[a[i]][r]-1;
                if(l<=r) update(1,1,n,l,r,-1);
            }
            if(siz>=k){
                int l=siz-k-1,r=siz-k;
                if(l<0) l=1;
                else l=pos[a[i]][l]+1;
                r=pos[a[i]][r];
                update(1,1,n,l,r,1);
            }
            int tmp=ask(1,1,n,1,i);
            if(tmp>0) ans=max(ans,i-tmp+1);
        }
        printf("%d\n",ans);
    }
    return 0;
}
相關文章
相關標籤/搜索