zoukankan      html  css  js  c++  java
  • [BZOJ 2653]middle

    Description

    题库链接

    一个长度为 (n) 的序列 (A) ,设其排过序之后为 (B) ,其中位数定义为 (Bleft[leftlfloorfrac{n}{2} ight floor ight]) ,其中 (A,B)(0) 开始标号。给你一个长度为 (n) 的序列 (S) 。回答 (Q) 个这样的询问: (S) 的左端点在 ([a,b]) 之间,右端点在 ([c,d]) 之间的子序列中,最大的中位数。

    强制在线。

    (1leq nleq 20000,1leq Qleq 25000)

    Solution

    二分答案。

    对于 (<mid) 的数变为 (-1) ,而 (geq mid) 的数变为 (1)

    那么只要统计 ([a,b]) 中的最大后缀, ((b,c)) 总和,及 ([c,d]) 中的最大前缀。

    主席树维护,乱搞一下就好了。

    Code

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int N = 20000;
    
    int n, Q, mp[N+5], a[N+5], tot, q[5], last_ans;
    vector<int>to[N+5];
    
    struct node {
        int lmax, rmax, tol;
        node (int _lmax = 0, int _rmax = 0, int _tol = 0) {lmax = _lmax, rmax = _rmax, tol = _tol; }
        node operator + (const node &b) const {
            node ans;
            ans.tol = tol+b.tol, ans.lmax = max(lmax, tol+b.lmax), ans.rmax = max(b.rmax, b.tol+rmax);
            return ans;
        }
    };
    struct Segment_tree {
        node sgm[N*50+5]; int ch[N*50+5][2], root[N+5], pos;
        int cpynode(int o) {++pos; sgm[pos] = sgm[o]; ch[pos][0] = ch[o][0], ch[pos][1] = ch[o][1]; return pos; }
        void build(int &o, int l, int r) {
            o = cpynode(o); int mid = (l+r)>>1;
            if (l == r) {sgm[o] = node(1, 1, 1); return; }
            build(ch[o][0], l, mid); build(ch[o][1], mid+1, r);
            sgm[o] = sgm[ch[o][0]]+sgm[ch[o][1]];
        }
        void update(int &o, int l, int r, int loc) {
            o = cpynode(o); int mid = (l+r)>>1;
            if (l == r) {sgm[o] = node(-1, -1, -1); return; }
            if (loc <= mid) update(ch[o][0], l, mid, loc);
            else update(ch[o][1], mid+1, r, loc);
            sgm[o] = sgm[ch[o][0]]+sgm[ch[o][1]];
        }
        node query(int o, int l, int r, int a, int b) {
            if (a <= l && r <= b) return sgm[o]; int mid = (l+r)>>1;
            if (a <= mid && b > mid) return query(ch[o][0], l, mid, a, b)+query(ch[o][1], mid+1, r, a, b);
            if (b <= mid) return query(ch[o][0], l, mid, a, b);
            return query(ch[o][1], mid+1, r, a, b);
        }
    }T;
    bool check(int x, int a, int b, int c, int d) {
        int val = 0;
        if (b+1 <= c-1) val = T.query(T.root[x], 1, n, b+1, c-1).tol;
        val += T.query(T.root[x], 1, n, a, b).rmax+T.query(T.root[x], 1, n, c, d).lmax;
        return val >= 0;    
    }
    void work() {
        scanf("%d", &n); tot = n;
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]), mp[i] = a[i];
        sort(mp+1, mp+n+1); tot = unique(mp+1, mp+tot+1)-mp-1;
        for (int i = 1; i <= n; i++) a[i] = lower_bound(mp+1, mp+tot+1, a[i])-mp, to[a[i]].pb(i);
        T.build(T.root[1], 1, n);
        for (int i = 2; i <= tot; i++) {
            T.root[i] = T.root[i-1];
            for (int j = 0, sz = to[i-1].size(); j < sz; j++)
                T.update(T.root[i], 1, n, to[i-1][j]);
        }
        scanf("%d", &Q);
        while (Q--) {
            for (int i = 0; i < 4; i++) scanf("%d", &q[i]), (q[i] += last_ans) %= n, ++q[i];
            sort(q, q+4);
            int L = 1, R = tot;
            while (L <= R) {
                int mid = (L+R)>>1;
                if (check(mid, q[0], q[1], q[2], q[3])) last_ans = mp[mid], L = mid+1;
                else R = mid-1;
            }
            printf("%d
    ", last_ans);
        }
    }
    int main() {work(); return 0; }
  • 相关阅读:
    AJAX
    前端上传文件 后端PHP获取文件
    PHP基础语法
    JS错误记录
    JS学习笔记
    python利用xlrd读取excel文件始终报错原因
    安装xlwt和xlrd
    编程菜鸟的日记-Linux无处不在
    编程菜鸟的日记-《软件测试》Ron Patton著-读书笔记
    编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第6章编程练习9
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8798337.html
Copyright © 2011-2022 走看看