[BZOJ3343]教主的魔法

试题描述

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

输入

第1行为两个整数NQQ为问题数与教主的施法数总和。
第2行有N个正整数,第i个数代表第i个英雄的身高。
第3到第Q+2行每行有一个操作:
(1)若第一个字母为“M”,则紧接着有三个数字LRW。表示对闭区间 [LR] 内所有英雄的身高加上W
(2)若第一个字母为“A”,则紧接着有三个数字LRC。询问闭区间 [LR] 内有多少英雄的身高大于等于C

输出

对每个“A”询问输出一行,仅含一个整数,表示闭区间 [LR] 内身高大于等于C的英雄数。

输入示例


A
M
A

输出示例


数据规模及约定

对30%的数据,N≤1000,Q≤1000。

对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000。

题解

这题询问较少,但 N 比较大,可以往 O(Q√n) 复杂度的算法这个方向去想,况且这个题目用数据结构很难维护,所以就会想到分块。

想到分块之后就很简单了,每个块内部排一遍序,整块查询时可以二分,边上两块就可以暴力处理了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 1000010
#define maxb 1010
int n, q, A[maxn], Blo[maxn], st[maxb], en[maxb], addv[maxb], cb, pos[maxn]; void update(int l, int r, int val) {
int bl = pos[l], br = pos[r];
if(br - bl < 2) {
for(int i = st[bl]; i <= en[br]; i++) A[i] += addv[pos[i]]; addv[bl] = addv[br] = 0;
for(int i = l; i <= r; i++) A[i] += val;
for(int i = st[bl]; i <= en[br]; i++) Blo[i] = A[i];
sort(Blo + st[bl], Blo + en[bl] + 1);
sort(Blo + st[br], Blo + en[br] + 1);
return ;
}
for(int i = st[bl]; i <= en[bl]; i++) A[i] += addv[bl]; addv[bl] = 0;
for(int i = st[br]; i <= en[br]; i++) A[i] += addv[br]; addv[br] = 0;
for(int i = l; i <= en[bl]; i++) A[i] += val;
for(int i = st[br]; i <= r; i++) A[i] += val;
for(int i = st[bl]; i <= en[bl]; i++) Blo[i] = A[i]; sort(Blo + st[bl], Blo + en[bl] + 1);
for(int i = st[br]; i <= en[br]; i++) Blo[i] = A[i]; sort(Blo + st[br], Blo + en[br] + 1);
for(int i = bl + 1; i <= br - 1; i++) addv[i] += val;
return ;
}
int query(int l, int r, int val) {
int bl = pos[l], br = pos[r], ans = 0;
if(br - bl < 2) {
for(int i = st[bl]; i <= en[br]; i++) A[i] += addv[pos[i]], Blo[i] += addv[pos[i]];
addv[bl] = addv[br] = 0;
for(int i = l; i <= r; i++) ans += (A[i] >= val);
return ans;
}
for(int i = st[bl]; i <= en[bl]; i++) A[i] += addv[bl], Blo[i] += addv[bl]; addv[bl] = 0;
for(int i = st[br]; i <= en[br]; i++) A[i] += addv[br], Blo[i] += addv[br]; addv[br] = 0;
for(int i = l; i <= en[bl]; i++) ans += (A[i] >= val);
for(int i = st[br]; i <= r; i++) ans += (A[i] >= val);
for(int i = bl + 1; i <= br - 1; i++) {
int x = lower_bound(Blo + st[i], Blo + en[i] + 1, val - addv[i]) - Blo;
if(Blo[x] >= val - addv[i]) x--;
if(en[i] > x) ans += en[i] - x;
}
return ans;
} int main() {
n = read(); q = read();
int t = (int)(sqrt(n) + .5);
for(int i = 1; i <= n; i++) {
A[i] = Blo[i] = read();
int ni = (i - 1) / t + 1; cb = ni;
if(!st[ni]) st[ni] = i; en[ni] = i;
pos[i] = ni;
} for(int i = 1; i <= cb; i++) sort(Blo + st[i], Blo + en[i] + 1);
while(q--) {
char tp = Getchar();
while(!isalpha(tp)) tp = Getchar();
int ql = read(), qr = read(), val = read();
if(tp == 'M') update(ql, qr, val);
if(tp == 'A') printf("%d\n", query(ql, qr, val));
} return 0;
}

教主的这个魔法能不能在我身上用一下啊 QAQ

[BZOJ3343]教主的魔法的更多相关文章

  1. BZOJ3343: 教主的魔法 分块

    2016-05-28  10:27:19 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3343 比较显然的分块题,分块后块内排序,维护整块的附 ...

  2. 【分块】bzoj3343: 教主的魔法

    3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 631  Solved: 272[Submit][Status][Discuss ...

  3. bzoj千题计划154:bzoj3343: 教主的魔法

    http://www.lydsy.com/JudgeOnline/problem.php?id=3343 high记录原始身高 HIGH记录每块排序之后的身高 不满一块的直接对high操作,重排之后再 ...

  4. bzoj3343: 教主的魔法 分块 标记

    修改:两边暴力重构,中间打标记.复杂度:O(n0.5) 查询:中间二分两边暴力.O(n0.5logn0.5) 总时间复杂度O(n*n0.5logn0.5) 空间复杂度是n级别的 标记不用下传因为标记不 ...

  5. [bzoj3343]教主的魔法——分块

    Brief description 给定一个数列,您需要支持一下两种操作: 给[l,r]同加一个数 询问[l,r]中有多少数字大于或等于v Algorithm analyse 这个题一时想不到什么有效 ...

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

    题意:维护一个数列,给出维护区间加法,询问区间内大于等于某个值的元素个数. 算法:分块.因为本题第二问显然可以用二分的思想,但是这貌似并不符合区间可加性,线段树好像就不好用了呢.所以本蒟蒻学习了分块. ...

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

    传送门:https://www.luogu.org/problemnew/show/P2801 参考:http://hzwer.com/2784.html  感觉思路无比清晰:) ps:我在洛谷A的, ...

  8. 【bzoj3343】教主的魔法 分块

    [bzoj3343]教主的魔法 2014年4月26日8092 Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了 ...

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

    3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 950  Solved: 414[Submit][Status][Discuss ...

随机推荐

  1. Ajax在调用含有SoapHeader的webservice方法

    ·         [WebService(Namespace = "http://tempuri.org/")] ·             [WebServiceBinding ...

  2. ubuntu中管理用户和用户组

    1. 添加一个用户组并指定id为1002 sudo groupadd -g 1002 www 2. 添加一个用户到www组并指定id为1003 sudo useradd wyx -g 1002 -u ...

  3. C#基础知识系列二(值类型和引用类型、可空类型、堆和栈、装箱和拆箱)

    前言 之前对几个没什么理解,只是简单的用过可空类型,也是知道怎么用,至于为什么,还真不太清楚,通过整理本文章学到了很多知识,也许对于以后的各种代码优化都有好处. 本文的重点就是:值类型直接存储其值,引 ...

  4. Javascript基础系列之(六)循环语句(while语句)

    循环语句的作用是反复的执行同一段代码,尽管分几种不同的类型,但其原理几乎相同:只要给定的条件满足,包含在循环体内的语句会不断执行,一旦条件不再满足则终止. while循环是前测试循环,这意味着是否终止 ...

  5. 每天一个linux命令(49):ss命令

    ss是Socket Statistics的缩写.顾名思义,ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容.但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信 ...

  6. 另一套Oracle SQL练习题,更新参考答案

    题干: create table student( sno ) primary key, sname ), sage ), ssex ) ); create table teacher( tno ) ...

  7. iOS开发小技巧--设置cell左右有空隙,设置分割线的新思路,重写setFrame:让别人在外界无法修改控件的大小

    如图:需要自定义cell

  8. LINQ构建交叉表

    最近碰到客户的一个需求.使用交叉表来显示客户数据.也就是以同时以行头和列头交叉形式显示数据内容.同时要求即使有些列没有数据,也需要显示该列内容,并设置默认值. 说明: “交叉表”对象是一个网格,用来根 ...

  9. 基本的mediaQuery写法,不复习又忘记了

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  10. 在Linux中怎么把用户添加到组中

    (1)添加用户test,初始密码123456,该用户的主目录为/home/share,用户的基本组为root,用户的shell为/bin/tcsh,要求将该用户加到mail和new组中.请问该怎么做啊 ...