[Noip模拟题]教主的魔法
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 129 Solved: 57
Description
教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一
次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。每个人的身高一开始都是不超过1000的正整数
。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合
区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)CYZ、光哥和ZJQ等人不信教主的邪,于是他
们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。WD巨懒,于是他
把这个回答的任务交给了你。
次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。每个人的身高一开始都是不超过1000的正整数
。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合
区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)CYZ、光哥和ZJQ等人不信教主的邪,于是他
们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。WD巨懒,于是他
把这个回答的任务交给了你。
Input
第1行为两个整数N、Q。Q为问题数与教主的施法数总和。
第2行有N个正整数,第i个数代表第i个英雄的身高。
第3到第Q+2行每行有一个操作:
(1)若第一个字母为"M",则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。
(2)若第一个字母为"A",则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。
N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000
第2行有N个正整数,第i个数代表第i个英雄的身高。
第3到第Q+2行每行有一个操作:
(1)若第一个字母为"M",则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。
(2)若第一个字母为"A",则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。
N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000
Output
对每个"A"询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于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
【输入输出样例说明】
原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。
教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。
这不是我这个蒟蒻能够做出来的题,太难了,改了一个世纪
具体思路看这里https://www.cnblogs.com/wzx-RS-STHN/
1 #include<bits/stdc++.h>
2 #pragma GCC optimize("O3")
3 #pragma GCC optimize("O2")
4 using namespace std;
5 typedef long long ll;
6 ll belong[1000001],n,q,a[1000001],tag[1000001],block,b[1000001];
7 ll L(ll i) {
8 return (i-1)*block+1;
9 }
10 ll R(ll i) {
11 return i*block;
12 }
13 ll rebuild(ll x) {
14 for(ll i=L(belong[x]); i<=R(belong[x]); i++)
15 b[i]=a[i];
16 sort(b+L(belong[x]),b+R(belong[x])+1);
17 }
18 void add(ll l,ll r,ll c) {
19 if(belong[l]==belong[r]) {
20 for(ll i=l; i<=r; i++)
21 a[i]+=c;
22 rebuild(l);
23 } else {
24 for(ll i=belong[l]+1; i<=belong[r]-1; i++)
25 tag[i]+=c;
26 for(ll i=l; i<=R(belong[l]); i++)
27 a[i]+=c;
28 rebuild(l);
29 for(ll i=L(belong[r]); i<=r; i++)
30 a[i]+=c;
31 rebuild(r);
32 }
33 }
34 ll find(ll l,ll r,ll c) {
35 ll ans=0;
36 if(belong[l]==belong[r]) {
37 for(ll i=l; i<=r; i++)
38 if(a[i]+tag[belong[i]]>=c)
39 ans++;
40 return ans;
41 } else {
42 for(ll i=belong[l]+1; i<belong[r]; i++) {
43 ll l=L(i);
44 ll r=R(i);
45 ll tot=0,mid;
46 while(l<=r) {
47 mid=(l+r)>>1;
48 if(b[mid]+tag[i]>=c)
49 r=mid-1,tot=R(i)-mid+1;
50 else
51 l=mid+1;
52 }
53 ans+=tot;
54 }
55 for(ll i=l; i<=R(belong[l]); i++)
56 if(a[i]+tag[belong[i]]>=c)
57 ans++;
58 for(ll i=L(belong[r]); i<=r; i++)
59 if(a[i]+tag[belong[i]]>=c)
60 ans++;
61 return ans;
62 }
63 }
64 int main() {
65 scanf("%lld%lld",&n,&q);
66 block=sqrt(n);
67 for(ll i=1; i<=n; i++) {
68 scanf("%lld",&a[i]);
69 belong[i]=(i-1)/block+1;
70 b[i]=a[i];
71 }
72 ll t=n/block;
73 if(n%block)
74 t++;
75 for(ll i=1; i<=t; i++)
76 sort(b+L(i),b+R(i)+1);
77 char otp;
78 ll l,r,c;
79 for(ll i=1; i<=q; i++) {
80 cin>>otp;
81 scanf("%lld %lld %lld",&l,&r,&c);
82 if(otp=='M')
83 add(l,r,c);
84 else
85 printf("%lld\n",find(l,r,c));
86 }
87 return 0;
88 }
来源:oschina
链接:https://my.oschina.net/u/4372568/blog/4325622