P2801 教主的魔法

题目描述:这里

思路:

这题似乎是道分块裸题。在查询时,我们可以对每个块进行排序,然后二分查找≥k的元素,输出答案。

不幸的是,这道题有点卡分块。我们可以改变块的大小和加入优化进行卡常。

代码:

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
using namespace std;

template < typename T > void read(T &x)
{
    int f = 1;x = 0;char c = getchar();
    for (;!isdigit(c);c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c);c = getchar()) x = x * 10 + c - '0';
    x *= f;
}

int block, num, l[1005], r[1005], belong[1000005], a[1000005], tag[1005], n, q;

void build()
{
    block = sqrt(n / log2(n));
    num = n / block;
    if(n % block) num++;
    for(int i = 1;i <= num;i++)
    {
        l[i] = (i - 1) * block + 1;
        r[i] = i * block;
    }
    r[num] = n;
    for(int i = 1;i <= n;i++)
        belong[i] = (i - 1) / block;
}

void update(int x, int y, int w)
{
    if(belong[x] == belong[y])
    {
        for(int i = x;i <= y;i++)
            a[i] += w;
    }
    else 
    {
        for(int i = x;i <= r[belong[x]];i++)
            a[i] += w;
        for(int i = l[belong[y]];i <= y;i++)
            a[i] += w;
        for(int i = belong[x] + 1;i <= belong[y] - 1;i++)
            tag[i] += w;
    }
}

int query(int x, int y, int k)
{
    if(belong[x] == belong[y])
    {
        int sum = 0;
        for(int i = x;i <= y;i++)
            if(a[i] + tag[belong[x]] >= k)
                sum++;
        return sum;
    }
    else
    {
        int sum = 0;
        for(int i = x;i <= r[belong[x]];i++)
            if(a[i] + tag[belong[x]] >= k)
                sum++;
        for(int i = l[belong[y]];i <= y;i++)
            if(a[i] + tag[belong[y]] >= k)
                sum++;
        for(int i = belong[x] + 1;i <= belong[y] - 1;i++)
        {
            sort(a + l[i], a + r[i] + 1);
            int lft = l[i], rgh = r[i];
            while(lft <= rgh)
            {
                int mid = (lft + rgh) / 2;
                if(a[mid] + tag[i] >= k)
                    rgh = mid - 1;
                else lft = mid + 1;
            }
            sum += block - lft + 1;
        }
        return sum;
    }
}

int main()
{
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    cin >> n >> q;
    for(int i = 1;i <= n;i++)
        read(a[i]);
    for(int i = 1;i <= q;i++)
    {
        char c;
        cin >> c;
        if(c == 'M')
        {
            int x, y, w;
            read(x);
            read(y);
            read(w);
            update(x, y, w);
        }
        if(c == 'A')
        {
            int x, y, k;
            read(x);
            read(y);
            read(k);
            cout << query(x, y, k) << endl;
        }
    }
    return 0;
}

 

上一篇:1005考试T3


下一篇:2019蓝桥杯国赛C++B组程序题部分