zoukankan      html  css  js  c++  java
  • 【CF-484E】Sign on Fence && 【luogu-P2839】[国家集训队]middle (二分+主席树的妙用整理)

    【CF-484E】Sign on Fence 题目链接:https://codeforces.ml/contest/484/problem/E

    【luogu-P2839】[国家集训队]middle 题目链接:https://www.luogu.com.cn/problem/P2839

    思路

    这两道题都应用了一个思想:将小于(等于)其值的数的位置和大于其值的位置分开讨论。

    具体可以在这两行代码实现:

    for (int i = 1; i <= n; i++) {
        vec[h[i]].push_back(i);
    }
    root[0] = tree.build(1, n);
    for (int i = 1; i <= Discrete::blen; i++) {
        root[i] = root[i-1];
        for (auto e: vec[i]) {
        root[i] = tree.update(root[i], e, 0, 1, n);
    }
    

    【CF-484E】Sign on Fence 具体思路

    二分答案,将值大于二分出来的 (mid) 的位置置为 (1),检查在区间连续范围内是否有一段长度为 (k)

    【CF-484E】Sign on Fence AC代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN = 1e5 + 5;
    
    namespace Discrete {      // 祖传离散化
        int b[MAXN], blen, btol;
        void insert(int x) { b[btol++] = x; }
        void init() {
            sort(b, b + btol);
            blen = unique(b, b + btol) - b;
        }
        int val2id(int x) {
            return lower_bound(b, b + blen, x) - b + 1;
        }
        int id2val(int x) {return b[x-1];}
    }
    using Discrete::val2id;
    using Discrete::id2val;
    
    class HJT {
    public:
        struct node {
            int ch[2];
            int pre, suf, len;
            node() {
                ch[0] = ch[1] = pre = suf = len  = 0;
            }
        } T[MAXN*70];
        int tot = 0;
    
    #define lson T[rt].ch[0]
    #define rson T[rt].ch[1]
    
        inline void push_up(int rt, int be, int en) {
            T[rt].pre = T[lson].pre, T[rt].suf = T[rson].suf;
            T[rt].len = max(T[lson].suf + T[rson].pre, max(T[lson].len, T[rson].len));
            int mid = (be + en) >> 1;
            if (T[lson].pre == mid-be+1) T[rt].pre += T[rson].pre;
            if (T[rson].suf == en- (mid+1) + 1) T[rt].suf += T[lson].suf;
        }
    
        int build(int l, int r) {
            int nrt = ++tot;
            if (l == r) {
                T[nrt].len = T[nrt].pre = T[nrt].suf = 1;
                return nrt;
            }
            int mid = (l + r) >> 1;
            T[nrt].ch[0] = build(l, mid), T[nrt].ch[1] = build(mid + 1, r);
            push_up(nrt, l, r);
            return nrt;
        }
    
        int update(int rt, int pos, int v, int be, int en) {
            int nrt = ++tot;
            if (be == en) {
                T[nrt].len = T[nrt].pre = T[nrt].suf = v;
                return nrt;
            }
            int mid = (be + en) >> 1;
            if (pos <= mid) {
                T[nrt].ch[0] = update(lson, pos, v, be, mid);
                T[nrt].ch[1] = rson;
            } else {
                T[nrt].ch[0] = lson;
                T[nrt].ch[1] = update(rson, pos, v, mid + 1, en);
            }
            push_up(nrt, be, en);
            return nrt;
        }
    
        node query_max(int rt, int L, int R, int be, int en) {
            if (L <= be && en <= R) return T[rt];
            int mid = (be + en) >> 1;
            if (R <= mid) return query_max(lson, L, R, be, mid);
            else if (L > mid) return query_max(rson, L, R, mid+1, en);
            else {
                node ans;
                node ansl = query_max(lson, L, R, be, mid);
                node ansr = query_max(rson, L, R, mid+1, en);
                ans.pre = ansl.pre, ans.suf = ansr.suf;
                ans.len = max(ansl.suf + ansr.pre, max(ansl.len, ansr.len));
                if (ansl.pre == mid - be + 1) ans.pre += ansr.pre;
                if (ansr.suf == en - (mid+1) + 1) ans.suf += ansl.suf;
                return ans;
            }
        }
    }tree;
    
    
    
    
    int h[MAXN], root[MAXN];
    vector<int> vec[MAXN];
    int n;
    bool check(int mid, int l, int r, int k) {
       // printf("%d
    ", tree.query_max(root[mid-1], l, r, 1, n).len);
        if (tree.query_max(root[mid-1], l, r, 1, n).len >= k) return 1;
        else return 0;
    }
    
    int main() {
    
        scanf("%d", &n);
        Discrete::btol = 0;
        for (int i = 1; i <= n; i++) scanf("%d", &h[i]), Discrete::insert(h[i]);
        Discrete::init();
        for (int i = 1; i <= n; i++) h[i] = val2id(h[i]);
    
        for (int i = 1; i <= n; i++) {
            vec[h[i]].push_back(i);
        }
    
        root[0] = tree.build(1, n);
    
        for (int i = 1; i <= Discrete::blen; i++) {
            root[i] = root[i-1];
            for (auto e: vec[i]) {
                root[i] = tree.update(root[i], e, 0, 1, n);
            }
        }
    
        int m; scanf("%d", &m);
        while (m--) {
            int l, r, k; scanf("%d%d%d", &l, &r, &k);
            int L = 1, R = Discrete::blen;
            while (L < R) {
                int mid = (L+R+1)>>1;
                if (check(mid,l,r, k)) L = mid;
                else R = mid-1;
            }
            printf("%d
    ", id2val(L));
        }
    
    }
    
    /*
    10
    1 2 3 4 5 6 7 8 9 10
    1
    2 7 5
    */
    

    【luogu-P2839】[国家集训队]middle 具体思路

    二分枚举中位数,应用到具体的性质为:如果一段数将大于 (mid) 的数赋为 (-1),小于 (mid) 的数赋值为 (1),那么和 (= 0) 的话,那么则可取。

    再在查询的范围内寻找前缀和后缀最大的和,若和 (geq 0),则代表这段序列可以通过缩小来使得最终的和 (= 0)

    【luogu-P2839】[国家集训队]middle AC代码

    #include <bits/stdc++.h>
    
    #define inf 0x3f3f3f3f
    #define pb push_back
    using namespace std;
    const int MAXN = 2e4 + 5;
    
    namespace Discrete {      // 祖传离散化
        int b[MAXN << 1], btol, blen;
        void insert(int x) { b[btol++] = x; }
        void init() {
            sort(b, b + btol);
            blen = unique(b, b + btol) - b;
        }
        int val2id(int x) { return lower_bound(b, b + blen, x) - b + 1; }
        int id2val(int x) { return b[x - 1]; }
    }
    using Discrete::val2id;
    using Discrete::id2val;
    
    
    class HJT {
    public:
        struct node {
            int ch[2];
            int pre, suf, sum;
            node() {
                ch[0] = ch[1] = pre = suf = sum = 0;
            }
        } T[MAXN * 70];
        int tot;
    #define lson T[rt].ch[0]
    #define rson T[rt].ch[1]
    
        inline void push_up(int rt) {
            T[rt].sum = T[lson].sum + T[rson].sum;
            T[rt].pre = max(T[lson].pre, T[lson].sum + T[rson].pre);
            T[rt].suf = max(T[rson].suf, T[rson].sum + T[lson].suf);
        }
    
        int build(int l, int r) {
            int nrt = ++tot;
            if (l == r) {
                T[nrt].sum = T[nrt].pre = T[nrt].suf = 1;
                return nrt;
            }
            int mid = (l + r) >> 1;
            T[nrt].ch[0] = build(l, mid), T[nrt].ch[1] = build(mid + 1, r);
            push_up(nrt);
            return nrt;
        }
    
        int update(int rt, int pos, int v, int be, int en) {
            int nrt = ++tot;
            if (be == en) {
                T[nrt].sum = T[nrt].pre = T[nrt].suf = v;
                return nrt;
            }
            int mid = (be + en) >> 1;
            if (pos <= mid) {
                T[nrt].ch[0] = update(lson, pos, v, be, mid);
                T[nrt].ch[1] = rson;
            } else {
                T[nrt].ch[0] = lson;
                T[nrt].ch[1] = update(rson, pos, v, mid + 1, en);
            }
            push_up(nrt);
            return nrt;
        }
    
        int query_sum(int rt, int L, int R, int be, int en) {
            if (L <= be && en <= R) return T[rt].sum;
            int mid = (be + en) >> 1;
            int ans = 0;
            if (L <= mid) ans += query_sum(lson, L, R, be, mid);
            if (R > mid) ans += query_sum(rson, L, R, mid + 1, en);
            return ans;
        }
    
        node query_pre(int rt, int L, int R, int be, int en) {
            if (L <= be && en <= R) return T[rt];
            int mid = (be + en) >> 1;
            if (R <= mid) return query_pre(lson, L, R, be, mid);
            else if (L > mid) return query_pre(rson, L, R, mid + 1, en);
            else {
                node ans;
                node ansl = query_pre(lson, L, R, be, mid);
                node ansr = query_pre(rson, L, R, mid + 1, en);
                ans.sum = ansl.sum + ansr.sum;
                ans.pre = max(ansl.pre, ansl.sum + ansr.pre);
                return ans;
    
            }
        }
    
        node query_suf(int rt, int L, int R, int be, int en) {
            if (L <= be && en <= R) return T[rt];
            int mid = (be + en) >> 1;
            if (R <= mid) return query_suf(lson, L, R, be, mid);
            else if (L > mid) return query_suf(rson, L, R, mid + 1, en);
            else {
                node ans;
                node ansl = query_suf(lson, L, R, be, mid);
                node ansr = query_suf(rson, L, R, mid + 1, en);
                ans.sum = ansl.sum + ansr.sum;
                ans.suf = max(ansr.suf, ansr.sum + ansl.suf);
                return ans;
            }
        }
    } tree;
    
    
    int a[MAXN], root[MAXN];
    vector<int> vec[MAXN];
    
    int n;
    
    bool check(int mid, const vector<int> &q) {
        int sum = 0;
        if (q[1] + 1 <= q[2] - 1) sum = tree.query_sum(root[mid - 1], q[1] + 1, q[2] - 1, 1, n);
        sum += tree.query_suf(root[mid - 1], q[0], q[1], 1, n).suf;
        sum += tree.query_pre(root[mid - 1], q[2], q[3], 1, n).pre;
        if (sum >= 0) return 1;
        else return 0;
    }
    
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            Discrete::insert(a[i]);
        }
        Discrete::init();
    
        for (int i = 1; i <= n; i++) a[i] = val2id(a[i]);
    
        for (int i = 1; i <= n; i++) {
            vec[a[i]].pb(i);
        }
    
        root[0] = tree.build(1, n);
        for (int i = 1; i <= Discrete::blen; i++) {
            root[i] = root[i - 1];
            for (auto e: vec[i]) {
                root[i] = tree.update(root[i], e, -1, 1, n);
            }
        }
        int m;
        scanf("%d", &m);
        int lastans = 0;
        while (m--) {
            vector<int> q(4);
            scanf("%d%d%d%d", &q[0], &q[1], &q[2], &q[3]);
            for (int i = 0; i < 4; i++) q[i] = (q[i] + lastans) % n + 1;
            sort(q.begin(), q.end());
            int L = 1, R = Discrete::blen;
            while (L < R) {
                int mid = (L + R + 1) >> 1;
                if (check(mid, q)) L = mid;
                else R = mid - 1;
            }
            lastans = id2val(L);
            printf("%d
    ", lastans);
    
        }
    }
    
    /*
    5
    2 4 1 5 3
    1
    3 1 0 2
    */
    
  • 相关阅读:
    Debug相关的一些小技巧
    <Information Storage and Management> 读书笔记 之二
    <<Information Storage and Management>>读书笔记 之三
    LINQ to SQL语句(2)之Select/Distinct【转】
    Asp.Net MVC实践 探索UrlRouting并分析UrlHelper (基于ASP.NET MVC Preview 3) 【转】
    MVC学习之分页 【转】
    在 ASP.NET MVC 项目中使用 WebForm 【转】
    Asp.net Mvc Codeplex Preview 5 第三篇 实现Action参数传递繁杂类型 【转】
    jQuery入门[1]-构造函数 【转】
    LINQ to SQL语句(1)之Where【转】
  • 原文地址:https://www.cnblogs.com/tudouuuuu/p/14027127.html
Copyright © 2011-2022 走看看