[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/p/12902684.html
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 ",find(l,r,c)); 86 } 87 return 0; 88 }