BZOJ3343 教主的魔法 二分法+分块

Posted WDZRMPCBIT

tags:

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

题意:给定一个数列,维护:1、[L,R]之间所有的数+=W  2、求[L,R]中大于等于C的数的数量

题解:更新用add标记,头尾俩块暴力重构;查询将每个块排序然后二分找。

#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXS=1000+2;
struct BLOCK{
    int a[MAXS],b[MAXS],add;
}block[MAXS];
int N,M,S;
char s;

void Update(int l,int r,int x){
    if((l-1)%S){
        int p=(l-1)/S+1;

        for(int i=l-S*(p-1);i<=S && i<=r-(p-1)*S;i++) block[p].a[i]+=x;
        for(int i=1;i<=S;i++) block[p].b[i]=block[p].a[i];

        sort(block[p].b+1,block[p].b+S+1);
        l=p*S+1;
    }

    while(l+S-1<=r) block[l/S+1].add+=x,l+=S;

    if(r%S){
        int p=l/S+1;r-=S*(p-1);

        for(int i=1;i<=r;i++) block[p].a[i]+=x;
        for(int i=1;i<=S;i++) block[p].b[i]=block[p].a[i];
        sort(block[p].b+1,block[p].b+S+1);
    }
}

int Find(int p,int l,int r,int c){
    c-=block[p].add;

    int m=(l+r)>>1;
    while(l<=r){
        if(block[p].b[m]<c) l=m+1;
        else r=m-1;
        m=(l+r)>>1;
    }

    return S-l+1;
}

int Query(int l,int r,int c){
    int ret=0;

    if((l-1)%S){
        int p=(l-1)/S+1;
        for(int i=l-S*(p-1);i<=r-S*(p-1) && i<=S;i++)
            if(block[p].a[i]>=c-block[p].add) ret++;
        l=p*S+1;
    }

    while(l+S-1<=r) ret+=Find(l/S+1,1,S,c),l+=S;

    if(r%S){
        int p=l/S+1;
        for(int i=1;i<=r-S*(p-1);i++)
            if(block[p].a[i]>=c-block[p].add) ret++;
    }

    return ret;
}

int main(){
    memset(block,0X7F,sizeof(block));
    block[1].add=0;

    cin >> N >> M,S=(int)sqrt(N);
    for(int i=1,j=1,k=1;i<=N;i++,j++){
        cin >> block[k].a[j],block[k].b[j]=block[k].a[j];
        if(j==S || i==N){
            sort(block[k].b+1,block[k].b+j+1);
            k++,j=0,block[k].add=0;
        }
    }
    N=(N%S?N/S+1:N/S);

    for(int i=1,l,r,x;i<=M;i++){
        cin >> s;
        cin >> l >> r >> x;

        if(s==\'M\') Update(l,r,x);
        if(s==\'A\') cout << Query(l,r,x) << endl;
    }

    return 0;
}
View Code

 

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

BZOJ-3343教主的魔法+分块(大块排序二分)

BZOJ 3343 教主的魔法 分块

bzoj3343 教主的魔法分块入门By cellur925

bzoj 3343: 教主的魔法 分块

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

BZOJ 3343:教主的魔法(分块)