hdu6602---线段树

Posted vege-chicken-rainstar

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu6602---线段树相关的知识,希望对你有一定的参考价值。

Longest Subarray

题意:一个数列,每个元素大小都在1到C之间,求一个最长的子串,满足在这个子串中1到C之间的每个数字要么出现0次,要么出现至少K次。

题解:(i)从1到n枚举右端点,维护一个(tree[j])表示在(i)为右端点时以(j)为左端点可行的个数(这里的可行是指对于1到C之间的某一个数是否可行,即(j)(i)之间(X)的个数是否满足题意,(Xepsilon(1,C)))。那么对于固定的(i)显然当(tree[j]==C)([j,i])是一个可行区间,找出最小的(j)即可. 上述操作在线段树上维护.

#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); 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
",ans);
    }
    return 0;
}

以上是关于hdu6602---线段树的主要内容,如果未能解决你的问题,请参考以下文章

Longest Subarray(HDU6602+线段树)

HDU6602 Longest Subarray(思维+线段树区间修改维护最值)

2019杭电多校第二场hdu6602 Longest Subarray(线段树)

hdu-1540线段树刷题

HDU 5692 线段树

hdu6464 线段树