洛谷---P2801:教主的魔法(分块经典)

题目:

https://www.luogu.org/problemnew/show/P2801

分析:

先将数组分成sqrt(n)块,每块sqrt(n)个元素,区间修改时,利用线段树的lazy标记,如果待修改的区间包含了完整的块x,那么lazy[x] += c,剩余的区间暴力更新,为了方便查询,我们同时用另一个数组来维护每个块元素的有序性,因为有lazy标记,修改时我们只需要从新维护暴力修改的块的有序性,如果查询的区间包含了完整的块,那么可以在这个块中二分求出 >= c-lazy[x] 的元素个数,剩下的区间同样暴力查询

对于块x,左端点:(x-1) * sqrt(n) + 1,右端点:x * sqrt(n)

对于下标x,属于块(x-1)/sqrt(n) + 1

代码:

#include <bits/stdc++.h>

using namespace std;
const int MAXN = 1e6+15;
int a[MAXN],b[MAXN],pos[MAXN],lazy[MAXN],n,q,m,block;
void build(int x){
    int l = (x-1)*block+1,r = min(x*block,n);
    for(int i = l;i <= r; ++i) b[i] = a[i];
    sort(b+l,b+r+1);
}
void Updata(int l,int r,int v){
    if(pos[l] == pos[r]){
        for(int i = l;i <= r; ++i) a[i] += v;
    }
    else{
        for(int i = l;i <= pos[l]*block; ++i) a[i] += v;
        for(int i = (pos[r]-1)*block+1;i <= r; ++i) a[i] += v;
        for(int i = (pos[l]+1);i < pos[r]; ++i) lazy[i] += v;        
    }
    build(pos[l]);                           //pos[l]块的部分元素改变了,从新维护该块的有序性
    build(pos[r]);
}
int Query(int l,int r,int v){
    int res = 0;
    if(pos[l] == pos[r]){
        for(int i = l;i <= r; ++i) if(a[i]+lazy[pos[l]] >= v) res++;
    }
    else{
        for(int i = l;i <= pos[l]*block; ++i) if(a[i]+lazy[pos[i]] >= v) res++;
        for(int i = (pos[r]-1)*block+1;i <= r; ++i) if(a[i]+lazy[pos[i]] >= v) res++;
        for(int i = (pos[l]+1);i < pos[r]; ++i){
            int l = (i-1)*block+1,r = min(i*block,n);
            int tep = lower_bound(b+l,b+r+1,v-lazy[i]) - b;
            res += r-tep+1;
        }
    }
    return res;
}
int main(){
    cin >> n >> q;
    for(int i = 1;i <= n; ++i) cin >> a[i];
    block = sqrt(n*1.0);
    m = n / block + (n % block > 0);           //总块数
    for(int i = 1;i <= m; ++i) build(i);
    for(int i = 1;i <= n; ++i) pos[i] = (i-1)/block + 1;
    char c;
    int L,R,w;
    while(q--){
        cin >> c >> L >> R >> w;
        if(c == 'M') Updata(L,R,w);
        else cout << Query(L,R,w) << '\n';
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41157137/article/details/88887222