【分块】bzoj3343: 教主的魔法

3343: 教主的魔法

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 631  Solved: 272
[Submit][Status][Discuss]

Description

教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N

每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[LR](1≤LRN)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第LR)个英雄的身高)

CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [LR] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。

WD巨懒,于是他把这个回答的任务交给了你。

Input

第1行为两个整数NQQ为问题数与教主的施法数总和。

第2行有N个正整数,第i个数代表第i个英雄的身高。

第3到第Q+2行每行有一个操作:

(1)       若第一个字母为“M”,则紧接着有三个数字LRW。表示对闭区间 [LR] 内所有英雄的身高加上W

(2)       若第一个字母为“A”,则紧接着有三个数字LRC。询问闭区间 [LR] 内有多少英雄的身高大于等于C

Output

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

Sample Input

5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4

Sample Output

2
3

HINT

【输入输出样例说明】

原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。

【数据范围】

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

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


  新开一个数组b

  b中的每块中的元素有序

  每次updata:整块tag记录,小块暴力修改

  求query:小块暴力,大块二分.

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5
 6 #define maxn 1000001
 7
 8 using namespace std;
 9
10 int n,a[maxn],team[maxn],b[maxn],str[maxn],end[maxn],tag[1001];
11
12 inline int in()
13 {
14     int x=0;char ch=getchar();
15     while(ch<‘0‘||ch>‘9‘)ch=getchar();
16     while(ch<=‘9‘&&ch>=‘0‘)x=x*10+ch-‘0‘,ch=getchar();
17     return x;
18 }
19
20 void pre()
21 {
22     int T=sqrt(n),cnt;
23     for(int i=1;i<=n;i++)
24         team[i]=(i-1)/T+1;
25     cnt=team[n];
26     for(int i=1;i<=n;i++)end[team[i]]=i,b[i]=a[i];
27     for(int i=n;i>=1;i--)str[team[i]]=i;
28     for(int i=1;i<=cnt;i++)
29         sort(str[i]+b,b+end[i]+1);
30 }
31
32 void add(int l,int r,int c)
33 {
34     if(team[l]==team[r]){
35         for(int i=l;i<=r;i++)a[i]+=c;
36         for(int i=str[team[l]];i<=end[team[r]];i++)b[i]=a[i];
37         sort(str[team[l]]+b,end[team[l]]+b);
38         return;
39     }
40     for(int i=l;i<=end[team[l]];i++)
41         a[i]+=c;
42     for(int j=str[team[r]];j<=r;j++)
43         a[j]+=c;
44     for(int i=str[team[l]];i<=end[team[l]];i++)b[i]=a[i];
45     for(int i=str[team[r]];i<=end[team[r]];i++)b[i]=a[i];
46     sort(str[team[l]]+b,end[team[l]]+b+1);
47     sort(str[team[r]]+b,end[team[r]]+b+1);
48     for(int i=team[l]+1;i<=team[r]-1;i++)
49         tag[i]+=c;
50 }
51
52 int binary_search(int pos,int c)
53 {
54     int l=str[pos],r=end[pos];
55     if(b[r]<c)return r+1;
56     while(l<=r)
57     {
58         int mid=(l+r)>>1;
59         if(b[mid]<c)l=mid+1;
60         else r=mid-1;
61     }
62     return l;
63 }
64
65 int query(int l,int r,int c)
66 {
67     int ans=0;
68     if(team[l]==team[r]){
69         for(int i=l;i<=r;i++)if(a[i]+tag[team[l]]>=c)ans++;
70         return ans;
71     }
72     for(int i=l;i<=end[team[l]];i++)
73         if(a[i]+tag[team[l]]>=c)ans++;
74     for(int j=str[team[r]];j<=r;j++)
75         if(a[j]+tag[team[r]]>=c)ans++;
76     for(int i=team[l]+1;i<=team[r]-1;i++)
77         ans+=end[i]-binary_search(i,c-tag[i])+1;
78     return ans;
79 }
80
81 int main()
82 {
83     int q,u,v,c;
84     char sb;
85     n=in();q=in();
86     for(int i=1;i<=n;i++)a[i]=in();
87     pre();
88     for(int i=1;i<=q;i++)
89     {
90         sb=0;
91         while(sb!=‘A‘&&sb!=‘M‘)sb=getchar();
92         u=in(),v=in(),c=in();
93         if(sb==‘A‘)printf("%d\n",query(u,v,c));
94         else add(u,v,c);
95     }
96     return 0;
97 }

时间: 2024-12-28 01:20:39

【分块】bzoj3343: 教主的魔法的相关文章

[BZOJ3343] 教主的魔法|分块

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

BZOJ3343: 教主的魔法

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

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

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

【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)内

【bzoj3343】教主的魔法 分块

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

bzoj 3343: 教主的魔法 分块

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

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)

【bzoj3343】【教主的魔法】

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