• Gym-101470C


    Most Influential Pumpkin

    题意

    (n) 个元素的数组 (A)(k) 次操作,每次操作使得区间 ([L_i,R_i]) 内的数加 1,每次操作后你都要输出当前 (A) 数组的中位数。

    (1 le n,k le 6e4) , (n) 是奇数

    思路

    因为每次只进行加一操作,所以答案只可能是上一次的答案或者上一次的答案加 1.

    开一个数组 (B) ,初始化 (B=A) ,然后将 (B) 分块,使得 (B) 在块内有序。先处理出初始中位数 (Ans)

    对于每一次操作,小块里的直接暴力修改 (A) ,然后暴力重构 (B) ,对于连续的完整块,开一个标记数组 (tag) 表示该块全体增加了多少。

    对于每一次的答案,我们可以询问 (B) 内小于等于 (Ans) 的数的个数,若小于 (lceil dfrac n 2 ceil)(Ans) 加 1. ((O(sqrt nlogsqrt n)))

    /*
     * @Author: zhl
     * @LastEditTime: 2021-03-10 21:36:31
     */
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5 + 10;
    int n, m, A[N], id[N], B[N], l[N], r[N], tag[N];
    void block_sort(int idx) {
        for (int i = l[idx];i <= r[idx];i++)B[i] = A[i];
        sort(B + l[idx], B + r[idx] + 1);
    }
    void build() {
        int len = sqrt(n);
        for (int i = 1;i <= n;i++)id[i] = (i + len - 1) / len;
        for (int i = id[1];i <= id[n];i++) {
            l[i] = len * (i - 1) + 1;
            r[i] = len * i;
            tag[i] = 0;
        }
        r[id[n]] = n;
        for (int i = id[1];i <= id[n];i++)block_sort(i);
    }
    void updt(int L, int R) {
        for (int idx = id[L] + 1;idx <= id[R] - 1;idx++)tag[idx]++;
        if (id[L] == id[R]) {
            for (int i = L;i <= R;i++)A[i]++;
            block_sort(id[L]);
        }
        else {
            for (int i = L;i <= r[id[L]];i++)A[i]++;
            block_sort(id[L]);
            for (int i = l[id[R]];i <= R;i++)A[i]++;
            block_sort(id[R]);
        }
    }
    int cal(int v) {
        int res = 0;
        for (int idx = id[1];idx <= id[n];idx++) {
            res += upper_bound(B + l[idx], B + r[idx] + 1, v - tag[idx]) - (B + l[idx]);
        }
        return res;
    }
    int main() {
    #ifdef ONLINE_JUDGE
        freopen("f.in", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
        while (~scanf("%d%d", &n, &m) and n + m) {
            for (int i = 1;i <= n;i++)scanf("%d", A + i), B[i] = A[i];
            int mid = (n + 1) / 2;
            sort(B + 1, B + 1 + n);
            int ans = B[mid];
            build();
            for (int i = 1, L, R;i <= m;i++) {
                scanf("%d%d", &L, &R);
                updt(L, R);
                if (cal(ans) < mid)ans++;
    
                printf("%d
    ", ans);;
            }
        }
    }
    /*
    1 1
    1
    1 1
    3 4
    3 2 1
    1 3
    1 1
    3 3
    3 3
    0 0
    
    
    7 7
    1 1 1 3 3 3 3
    1 3
    5 7
    1 3
    1 4
    1 3
    4 4
    1 3
    0 0
    
     */
    
  • 相关阅读:
    C语言程序设计_zju——计算时间差
    C语言程序设计_zju——第1周编程练习_逆序的三位数
    常用CMD指令
    C#MVC Razor的Ajax.BeginForm里面的OnSuccess未执行(未成功跳转)
    发布带注释的dll
    读书笔记之《得未曾有》
    读书笔记之《高效人士的七个习惯》
    读书笔记之《好好说话》
    个人随笔之《关于选择》
    个人随笔之《关于心安》
  • 原文地址:https://www.cnblogs.com/sduwh/p/14516169.html
Copyright © 2020-2023  润新知