P2801 教主的魔法 (分块)

Posted 1625--h

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2801 教主的魔法 (分块)相关的知识,希望对你有一定的参考价值。

题目传送

长度为\(n(n\le 1000000)\)的数组,\(q(q\le 3000)\) 次操作。修改操作即将某个区间的值增加某个不大于1000的值,查询操作即查询某个区间比C大于等于的数有多少个

我们用一个数组\(add[i]\)来表示第\(i\)段增量,如果查询区间完全包含第\(i\)段,那么就相当于是在原数组中查找大于等于\(C-add[i]\)的数,怎么找?排序后二分找。而对于左右不完整的那部分,直接暴力查询就可以。

对于修改操作。整段的直接增加增量,不完整的直接修改原数组,然后重新排序即可。

假设一段长度为\(t\) 则复杂度\(O(C(t+nlog(t)\over t))\)

#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int a[N],b[N],be[N],L[N],R[N],add[N];
char op[3];
int l,r,x;
int n,m;
void change(int l,int r,int x)
    int p = be[l],q = be[r];
    if(p == q)
        for(int i=l;i<=r;i++)a[i] += x;
        for(int i=L[p];i<=R[p];i++)b[i] = a[i];
        sort(b+L[p],b+R[p]+1);
    
    else
        for(int i=p+1;i<=q-1;i++)add[i] += x;
        for(int i=l;i<=R[p];i++)a[i] += x;
        for(int i=L[p];i<=R[p];i++)b[i] = a[i];
        sort(b+L[p],b+R[p]+1);
        for(int i=L[q];i<=r;i++)a[i] += x;
        for(int i=L[q];i<=R[q];i++)b[i] = a[i];
        sort(b+L[q],b+R[q]+1);
    

void solve(int l,int r,int x)
    int res = 0;
    int p = be[l],q = be[r];
    if(p == q)
        for(int i=l;i<=r;i++)
            if(a[i] + add[p] >= x)res++;
        
        printf("%d\n",res);return;
    
    else
        for(int i=p+1;i<=q-1;i++)
            res += (R[i]-L[i]+1) - (lower_bound(b+L[i],b+R[i]+1,x-add[i]) - (b+L[i]));
        
        for(int i=l;i<=R[p];i++)if(a[i] + add[p] >= x)res++;
        for(int i=L[q];i<=r;i++)if(a[i] + add[q] >= x)res++;
        printf("%d\n",res);return ;
    

int main()
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i] = a[i];
    int t = sqrt(n);
    for(int i=1;i<=t;i++)
        L[i] = (i - 1) * t + 1;
        R[i] = i * t;
    
    if(R[t] < n)t++,L[t] = R[t-1] + 1,R[t] = n;
    for(int i=1;i<=t;i++)for(int j=L[i];j<=R[i];j++)be[j] = i;
    for(int i=1;i<=t;i++)
        sort(b+L[i],b+R[i]+1);
    
    while(m--)
        scanf("%s%d%d%d",op,&l,&r,&x);
        if(op[0] == 'M')change(l,r,x);
        else solve(l,r,x);
    
    return 0;

以上是关于P2801 教主的魔法 (分块)的主要内容,如果未能解决你的问题,请参考以下文章

[洛谷P2801]教主的魔法

教主的魔法(分块模板)

bzoj 3343: 教主的魔法 分块

BZOJ 3343: 教主的魔法 [分块]学习笔记

Luogu 2801 教主的魔法 | 分块模板题

教主的魔法[分块+二分]