zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 22 E. Army Creation(分块好题)

    E. Army Creation
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    As you might remember from our previous rounds, Vova really likes computer games. Now he is playing a strategy game known as Rage of Empires.

    In the game Vova can hire n different warriors; ith warrior has the type ai. Vova wants to create a balanced army hiring some subset of warriors. An army is called balanced if for each type of warrior present in the game there are not more than k warriors of this type in the army. Of course, Vova wants his army to be as large as possible.

    To make things more complicated, Vova has to consider q different plans of creating his army. ith plan allows him to hire only warriors whose numbers are not less than li and not greater than ri.

    Help Vova to determine the largest size of a balanced army for each plan.

    Be aware that the plans are given in a modified way. See input section for details.

    Input

    The first line contains two integers n and k (1 ≤ n, k ≤ 100000).

    The second line contains n integers a1a2, ... an (1 ≤ ai ≤ 100000).

    The third line contains one integer q (1 ≤ q ≤ 100000).

    Then q lines follow. ith line contains two numbers xi and yi which represent ith plan (1 ≤ xi, yi ≤ n).

    You have to keep track of the answer to the last plan (let's call it last). In the beginning last = 0. Then to restore values of li and ri for the ith plan, you have to do the following:

    1. li = ((xi + lastmod n) + 1;
    2. ri = ((yi + lastmod n) + 1;
    3. If li > ri, swap li and ri.
    Output

    Print q numbers. ith number must be equal to the maximum size of a balanced army when considering ith plan.

    Example
    input
    6 2
    1 1 1 2 2 2
    5
    1 6
    4 3
    1 1
    2 6
    2 6
    
    output
    2
    4
    1
    3
    2
    
    Note

    In the first example the real plans are:

    1. 1 2
    2. 1 6
    3. 6 6
    4. 2 4
    5. 4 6

    题目链接:E. Army Creation

    神队友突然给我一道题目,这题跟BZOJ 那个维护队列的分块做法一样,那道题是分块维护倒数第1个同样的数的出现的位置,这题是维护倒数第k个同样的数出现的位置,然后在块内二分即可。真的是一道好题。

    代码:

    #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 = 100010;
    const int M = 320;
    struct Block
    {
        int l, r;
    };
    Block B[M];
    vector<int>prepos[N];
    int arr[N], pre[N], ori[N], belong[N];
    int unit, bcnt;
    
    void reset(int bx)
    {
        sort(pre + B[bx].l, pre + B[bx].r + 1);
    }
    void init(int n)
    {
        int i;
        unit = sqrt(n);
        bcnt = n / unit;
        if (n % unit)
            ++bcnt;
        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);
    }
    int bs(int bx, int key)
    {
        int ans = -1;
        int L = B[bx].l, R = B[bx].r;
        while (L <= R)
        {
            int mid = MID(L, R);
            if (pre[mid] < key)
            {
                ans = mid;
                L = mid + 1;
            }
            else
                R = mid - 1;
        }
        return ~ans ? ans - B[bx].l + 1 : 0;
    }
    int query(int l, int r)
    {
        int bl = belong[l], br = belong[r];
        int ans = 0;
        if (bl == br)
        {
            for (int i = l; i <= r; ++i)
                if (ori[i] < l)
                    ++ans;
        }
        else
        {
            for (int i = l; i <= B[bl].r ; ++i)
                if (ori[i] < l)
                    ++ans;
            for (int i = B[br].l; i <= r; ++i)
                if (ori[i] < l)
                    ++ans;
            for (int i = bl + 1; i < br; ++i)
                ans += bs(i, l);
        }
        return ans;
    }
    int main(void)
    {
        int n, k, i;
        scanf("%d%d", &n, &k);
        for (i = 1; i <= n; ++i)
        {
            scanf("%d", &arr[i]);
            int sz = prepos[arr[i]].size();
            if (sz < k)
            {
                pre[i] = 0;
            }
            else
                pre[i] = prepos[arr[i]][sz - k];
            ori[i] = pre[i];
            prepos[arr[i]].push_back(i);
        }
        init(n);
        int last = 0;
        int q;
        scanf("%d", &q);
        while (q--)
        {
            int l, r;
            scanf("%d%d", &l, &r);
            l = (l + last) % n + 1;
            r = (r + last) % n + 1;
            if (l > r)
                swap(l, r);
            printf("%d
    ", last = query(l, r));
        }
        return 0;
    }
  • 相关阅读:
    vgrant使用简易教程
    php数组常用函数总结
    php面向对象基础知识整理之类中的属性和方法的使用
    apache和nginx的区别
    thinkphp发送邮箱(以thinkphp5作为示例)。
    利用html2canvas将当前网页保存为图片.
    作为一名程序员该如何思考自己的职业人生?
    js常用返回网页顶部几种方法
    如何本地搭建centos7虚拟主机?
    Spark报错
  • 原文地址:https://www.cnblogs.com/Blackops/p/6964751.html
Copyright © 2011-2022 走看看