zoukankan      html  css  js  c++  java
  • ZOJ 2112 Dynamic Rankings(带修改的区间第K大,分块+二分搜索+二分答案)

    Dynamic Rankings

    Time Limit: 10 Seconds      Memory Limit: 32768 KB

    The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

    Your task is to write a program for this computer, which

    - Reads N numbers from the input (1 <= N <= 50,000)

    - Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.


    Input

    The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.

    The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

    Q i j k or
    C i t

    It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

    There're NO breakline between two continuous test cases.


    Output

    For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

    There're NO breakline between two continuous test cases.


    Sample Input

    2
    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3
    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3


    Sample Output

    3
    6
    3
    6

     
     
    题目链接:ZOJ 2112
    突然发现用分块做很简单,每一个块维护区间内的有序序列,暴力修改+重构,查询的时候二分下答案,设当前的二分值为mid,如果区间内小于等于mid的数>=k则说明答案小于等于mid,否则答案大于mid。
    代码:
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 50010;
    const int M = 10010;
    const int BC = 233;
    struct Block
    {
        int l, r;
    };
    Block B[M];
    int arr[N], belong[N], unit, bcnt, b[N];
    int n, m;
    
    void reset(int x)
    {
        for (int i = B[x].l; i <= B[x].r; ++i)
            b[i] = arr[i];
        sort(b + B[x].l, b + B[x].r + 1);
    }
    void init()
    {
        unit = sqrt(n);
        bcnt = n / unit;
        if (n % unit)
            ++bcnt;
        int i;
        for (i = 1; i <= bcnt; ++i)
        {
            B[i].l = (i - 1) * unit + 1;
            B[i].r = i * unit;
        }
        B[bcnt].r = n;
        for (i = 1; i <= n; ++i)
            belong[i] = (i - 1) / unit + 1;
        for (i = 1; i <= bcnt; ++i)
            reset(i);
    }
    void update(int x, int t)
    {
        int bx = belong[x];
        arr[x] = t;
        reset(bx);
    }
    int bs(int x, int key)
    {
        int l = B[x].l, r = B[x].r;
        int ans = -1;
        while (l <= r)
        {
            int mid = MID(l, r);
            if (b[mid] <= key)
            {
                ans = mid;
                l = mid + 1;
            }
            else
                r = mid - 1;
        }
        return ~ans ? ans - B[x].l + 1 : 0;
    }
    int query(int l, int r, int k)
    {
        int L = 0, R = 1e9;
        int ans = 1;
        int bl = belong[l], br = belong[r], i;
        while (L <= R)
        {
            int tk = 0;
            int mid = MID(L, R);
            for (i = l; i <= B[bl].r; ++i)
                if (arr[i] <= mid)
                    ++tk;
            for (i = B[br].l; i <= r; ++i)
                if (arr[i] <= mid)
                    ++tk;
            for (i = bl + 1; i < br; ++i)
                tk += bs(i, mid);
            if (tk >= k)
            {
                ans = mid;
                R = mid - 1;
            }
            else
                L = mid + 1;
        }
        return ans;
    }
    int main(void)
    {
        int tcase, i;
        char ops[3];
        int l, r, k, x, t;
        scanf("%d", &tcase);
        while (tcase--)
        {
            scanf("%d%d", &n, &m);
            for (i = 1; i <= n; ++i)
                scanf("%d", &arr[i]);
            init();
            for (i = 1; i <= m; ++i)
            {
                scanf("%s", ops);
                if (ops[0] == 'Q')
                {
                    scanf("%d%d%d", &l, &r, &k);
                    printf("%d
    ", query(l, r, k));
                }
                else
                {
                    scanf("%d%d", &x, &t);
                    update(x, t);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    记一次动态依赖包版本过高解决过程
    Centos8更改国内源阿里云
    记一次vs2019安装GDB实现Cmake远程linux调试
    Tu te prends pour qui?
    中国高等教育是个啥:官僚主义的垄断黑洞
    关闭ThinkPad HDD APS Logging Service
    python Tlinter按钮接收多个参数
    第一章
    IE7的一个边界BUG
    让LumaQQ.NET支持接收群自定义表情和贴图
  • 原文地址:https://www.cnblogs.com/Blackops/p/6978441.html
Copyright © 2011-2022 走看看