BZOJ_3343_教主的魔法_分块+二分查找

题意:教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列被编号为1、2、……、N。每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤LRN)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第LR)个英雄的身高)询问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。

分析:暴力!

每一块用一个辅助数组来排序,询问时整块二分查找大于等于C的位置,零散的暴力重构。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
#define N 1000010
#define LL long long
void read(LL &x){
    int f=1;x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=(x<<3)+(x<<1)+s-‘0‘;s=getchar();}
    x*=f;
}
int L[1010],R[1010],pos[N],t,is[1010],add[1010],n,q;
LL a[N],b[N];
int find(int blo,LL x){
    int l=L[blo],r=R[blo]+1;
    while(l<r){
        int mid=l+r>>1;
        if(b[mid]<x)l=mid+1;
        else r=mid;
    }return R[blo]-l+1;
}
inline void pre(int blo){
    for(int i=L[blo];i<=R[blo];i++)b[i]=a[i];
    sort(b+L[blo],b+R[blo]+1);
}
void up(int l,int r,LL c){
    int p=pos[l],q=pos[r];
    if(p==q){
        for(int i=l;i<=r;i++){
            a[i]+=c;
        }
        pre(p);
    }else{
        for(int i=p+1;i<q;i++){
            add[i]+=c;
        }
        for(int i=l;i<=R[p];i++){
            a[i]+=c;
        }
        for(int i=L[q];i<=r;i++){
            a[i]+=c;
        }
        pre(p);pre(q);
    }
}
int query(int l,int r,LL c){
    int p=pos[l],q=pos[r];
    int ans=0;
    if(p==q){
        for(int i=l;i<=r;i++)if(a[i]+add[p]>=c)ans++;
    }else{
        for(int i=p+1;i<q;i++){
            ans+=find(i,c-add[i]);
        }
        for(int i=l;i<=R[p];i++){
            if(a[i]+add[p]>=c)ans++;
        }
        for(int i=L[q];i<=r;i++){
            if(a[i]+add[q]>=c)ans++;
        }
    }
    return ans;
}
char op[10];
int main(){
    scanf("%d%d",&n,&q);
    t=sqrt(n);
    for(int i=1;i<=t;i++){
        L[i]=R[i-1]+1,R[i]=t*i;
        for(int j=L[i];j<=R[i];j++){
            read(a[j]);pos[j]=i;
        }
    }
    if(n-t*t){
        t++;L[t]=R[t-1]+1;R[t]=n;
        for(int i=L[t];i<=R[t];i++){
            read(a[i]);pos[i]=t;
        }
    }
    for(int i=1;i<=t;i++)pre(i);
    int x,y,z;
    while(q--){
        scanf("%s%d%d%d",op,&x,&y,&z);
        if(op[0]==‘M‘){
            up(x,y,1ll*z);
        }else{
            printf("%d\n",query(x,y,1ll*z));
        }
    }
}

原文地址:https://www.cnblogs.com/suika/p/8457529.html

时间: 2024-09-30 23:58:18

BZOJ_3343_教主的魔法_分块+二分查找的相关文章

教主的魔法(分块模板)

教主的魔法(luogu) Description 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W.(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高) CYZ.光哥和ZJQ等人不信教主的邪,于是他们有

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

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3343 [题目大意] 给出一个数列,有区间加法操作,询问区间大于等于c的数字个数 [题解] 我们将数据分块,区间加法等价于各个块整块加法以及首位部分的个体加法, 由于要查询区间大于等于c的数字个数, 因此我们在每个块发生相对大小变动的时候对块内元素映射进行一次排序, 因为每次只有最左和最右的块相对大小发生变动,因此修改操作仍为O(sqrt(n)) 查询时我们二分查找每个块中满足大小的个

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

题意:维护一个数列,给出维护区间加法,询问区间内大于等于某个值的元素个数. 算法:分块.因为本题第二问显然可以用二分的思想,但是这貌似并不符合区间可加性,线段树好像就不好用了呢.所以本蒟蒻学习了分块. 这大概是本蒟蒻的第一题正式分块,思想是在hzwer学长的分块入门学的==. 什么是分块?我们维护数列(貌似树上也可以)信息时可以先采用分治的思想,把数列分成若干连续的块,维护信息可以统一在块上进行维护.假如有一个n元素的数列,根据均值不等式的数学知识(并不会证明),我们把每个块的大小设为根号n可以

【tyvj1463】智商问题 [分块][二分查找]

Background 各种数据结构帝~各种小姊妹帝~各种一遍AC帝~ 来吧! Description 某个同学又有很多小姊妹了他喜欢聪明的小姊妹 所以经常用神奇的函数来估算小姊妹的智商他得出了自己所有小姊妹的智商小姊妹的智商都是非负整数但是这个同学看到别的同学的小姊妹也喜欢用神奇的函数估算一下然后看看这个小姊妹在自己的小姊妹群体中排在第几位…(这么邪恶的兴趣…) InputFormat 第一行一个整数N 代表小姊妹的个数第二行N个整数 代表这位同学N个小姊妹的智商接下来若干行 每行一个整数代表这

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

题意:给定一个数列,维护:1.[L,R]之间所有的数+=W  2.求[L,R]中大于等于C的数的数量 题解:更新用add标记,头尾俩块暴力重构:查询将每个块排序然后二分找. #include <cmath> #include <ctime> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm

【bzoj3343】 教主的魔法(分块入门)

题意:一个含n个数的区间(n<=1000000),k次操作,两种操作: M a,b,c  将区间[a,b]中的每一个数加c; A a,b,c  查询区间[a,b]中大于c的数的个数: 思路:将区间分为sqrt(n)块,对每块进行排序: 对于查询区间,两端的块外区间暴力处理,中间的块内区间特殊处理(二分): 借助add标记,实现优化: #include<cstdio> #include<cstring> #include<algorithm> #include<

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

题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W.(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高) CYZ.光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高

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

3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1172  Solved: 526[Submit][Status][Discuss] Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)

【BZOJ-3343】教主的魔法 分块

3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 950  Solved: 414[Submit][Status][Discuss] Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内