zoukankan      html  css  js  c++  java
  • 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
    ",ans);
        }
        return 0;
    }
    /*
    7 5 2
    3 1 5 2 5 2 3
    
    
     */
  • 相关阅读:
    官方文档翻译-Today
    RAC & MVVM 学习资料整理
    35种常用字体
    中文字体的种类
    自言自语(三)--部分中文字体
    自言自语(二)--英文无衬线体和有衬线体
    sketch字体设置技巧(一)---通过锚点改变字体形态
    提高设计档次的8个方法
    知识汇总09~bootstrap-select在Vue中的封装
    知识汇总08~字符串截取
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11285401.html
Copyright © 2011-2022 走看看