zoukankan      html  css  js  c++  java
  • HDU6602 Longest Subarray hdu多校第二场 线段树

    HDU6602 Longest Subarray 线段树

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6602

    题意:

    给你一段区间,让你求最长的区间使得区间出现的数字的个数大于k

    题解:

    比较巧妙的的线段树更新的做法

    我们选择的区间吗,该区间内出现的数字的个数必须要满足条件

    我们转换一下,我们以当前点为右端点,往左找一个满足条件的左端点,即可更新答案

    我们将每个点给予一个权值C-1,更新这个点的数字上次出现的位置之前到现在这个位置-1的一段减1

    如果满足这个点的值出现的次数大于k次的话,我们将上一次满足出现k次出现的一段位置给加上1

    最后得到当前位置之前满足条件的左端点更新答案

    这里巧妙的使用了条件作为线段树查询的条件,所以线段树查询出来的左端点就是满足条件的最远的左端点

    代码:

    #include <set>
    #include <map>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    const int maxn = 3e5 + 5;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const double Pi = acos(-1);
    /*
    如果右端点固定,对于每种元素,可行的左端点下标是两段连续的区间。
    对于每种元素,将它的可行左端点区间在线段树中加1。
     当右端点右移的时候,维护C 种元素的可行左端点。
    查询时只要询问线段树中札小的、值为C 的下标即可。*/
    LL quick_pow(LL x, LL y) {
        LL ans = 1;
        while(y) {
            if(y & 1) {
                ans = ans * x % mod;
            } x = x * x % mod;
            y >>= 1;
        } return ans;
    }
    int n, C, k;
    int Max[maxn << 2];
    int lazy[maxn << 2];
    int pos[maxn << 2];
    void push_up(int rt) {
        Max[rt] = max(Max[ls], Max[rs]);
        pos[rt] = (Max[rt] == Max[ls] ? pos[ls] : pos[rs]);
    }
    void build(int l, int r, int rt) {
        Max[rt] = lazy[rt] = 0;
        pos[rt] = l;
        if(l == r) return;
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
    }
    void push_down(int rt) {
        if(lazy[rt]) {
            lazy[ls] += lazy[rt];
            lazy[rs] += lazy[rt];
            Max[ls] += lazy[rt];
            Max[rs] += lazy[rt];
            lazy[rt] = 0;
        }
    }
    void update(int L, int R, int val, int l, int r, int rt) {
        if(L > R) return;
        if(L <= l && r <= R) {
            Max[rt] += val;
            lazy[rt] += val;
            return;
        }
        push_down(rt);
        int mid = (l + r) >> 1;
        if(L <= mid) update(L, R, val, lson);
        if(R > mid) update(L, R, val, rson);
        push_up(rt);
    }
    int query(int L, int R, int l, int r, int rt) {
        if(Max[rt] != C) return 0;
        if(L <= l && r <= R) {
            return pos[rt];
        }
        int mid = (l + r) >> 1;
        push_down(rt);
        if(L <= mid) {
            int t = query(L, R, lson);
            if(t) return t;
        }
        if(R > mid) return query(L, R, rson);
        return 0;
    }
    vector<int> vec[maxn];
    int main() {
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        while(scanf("%d%d%d", &n, &C, &k) != EOF) {
            for(int i = 1; i <= C; i++) {
                vec[i].clear();
                vec[i].push_back(0);
            }
            build(1, n, 1);
            int ans = 0;
            for(int i = 1; i <= n; i++) {
                int c;
                scanf("%d", &c);
                update(i, i, C - 1, 1, n, 1);
                update(vec[c].back() + 1, i - 1, -1, 1, n, 1);
                vec[c].push_back(i);
                int p = vec[c].size() - k - 1;
                if(p >= 0) {
                    update(vec[c][p] + 1, vec[c][p + 1], 1, 1, n, 1);
                }
                int j = query(1, i, 1, n, 1);
                if(!j) continue;
                ans = max(ans, i - j + 1);
            }
            printf("%d
    ", ans);
    
    
        }
    
        return 0;
    }
    
  • 相关阅读:
    移动端拖拽
    原生js增加,移除类名
    js自执行函数
    页面加载初始化方法
    writing-mode,文字竖直书写,字符之间距离,单词之间距离
    滚动鼠标达到一点范围时的跑秒效果,从0开始一直加在规定时间内加到最大值
    haley解决中文字段名称字数不同时两端对齐的问题
    常用的一些css实现的小效果,比如三角形,小三角,阴影等
    html几个比较常用的颜色名称
    Spring--通过注解来配置bean
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/11253492.html
Copyright © 2011-2022 走看看