• 多校2 Longest Subarray 线段树


      题意:给定n C k     和序列ai(1-n)     求最长的区间长度  使得  该区间中所有出现的元素 的个数为0或>=k     所有数字都在1-C的范围内

    题解:

    如果右端点固定,对于每种元素,可行的左端点下标是两段连续的区间。
    对于每种元素,将它的可行左端点区间在线段树中加一。
    当右端点右移的时候,维护 C种元素的可行左端点。
    查询时只需要询问线段树中最小的、值为C  的下标即可。

    画个图思路就很清晰了  非常好的线段树题 

    注意维护最值下标的方式 

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define lson l,m,pos<<1
    #define rson m+1,r,pos<<1|1
    #define pb push_back
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    const int N=1e5+5;
    int t[N<<2],col[N<<2],x[N<<2];
    int C,k,n,m;
    vector<int>v[N];
    void up(int pos)
    {
        t[pos]=max(t[pos<<1],t[pos<<1|1]);
        x[pos]=(t[pos]==t[pos<<1])?x[pos<<1]:x[pos<<1|1];
    }
    void down(int pos)
    {
        if(col[pos])
        {
            t[pos<<1]+=col[pos];
            t[pos<<1|1]+=col[pos];
            col[pos<<1]+=col[pos];
            col[pos<<1|1]+=col[pos];
            col[pos]=0;
        }
    }
    void build(int l,int r,int pos)
    {
        x[pos]=l;col[pos]=0;
        if(l==r){t[pos]=0;return ; }
        int m=(l+r)>>1;build(lson);build(rson);up(pos);
    }
    void upsum(int L,int R,int v,int l,int r,int pos)
    {
        if(L>R)return ;
        if(L<=l&&r<=R){ col[pos]+=v;t[pos]+=v;return ;  }
        int m=(l+r)>>1;down(pos);
        if(L<=m)upsum(L,R,v,lson);
        if(R>m)upsum(L,R,v,rson);
        up(pos);
    }
    int qsum(int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            return t[pos]==C?x[pos]:0;
        }
        int m=(l+r)>>1;down(pos);
        if(L<=m)//这里一定要注意细节
        {
            int t=qsum(L,R,lson);
            if(t)return t;
        }
        if(R>m)return qsum(L,R,rson);
        return 0;
    }
    int c;
    int main()
    {
        while(cin>>n>>C>>k)
        {
            rep(i,1,C+1)v[i].clear(),v[i].pb(0);
            build(1,n,1);
            int ans=0;
            rep(i,1,n)
            {
                RI(c);
                upsum(i,i,C-1,1,n,1);
    
                upsum(v[c].back()+1,i-1,-1,1,n,1);
                v[c].pb(i);
                int p=(v[c].size()-k-1);
                if(p>=0)
                upsum(v[c][p]+1,v[c][p+1],1,1,n,1);
                int j=qsum(1,n,1,n,1);
                if(!j)continue;
                ans=max(ans,i-j+1);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HERO 3
    office的一些应用,
    网页之间的参数传弟
    一个好的数码网站
    C++遍历中删除std::hash_map元素问题
    【转】Asio与shared_ptr的一些注意事项
    delphi的字节对齐
    paypal的即时付款通知参数列表(PDT)
    vs2010下libevent的使用
    mysql 数据库 left join,right join, inner join 知识
  • 原文地址:https://www.cnblogs.com/bxd123/p/11241725.html
Copyright © 2020-2023  润新知