教主的魔法(分块模板)
Posted hsez-cyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了教主的魔法(分块模板)相关的知识,希望对你有一定的参考价值。
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行为两个整数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。
输出格式
对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。
Solution
分块用于区间加减和区间查大于某数的数的个数模板
排序后二分
Code
#include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #define ll long long using namespace std; const int N=1e6+10,M=1e3+10; struct node { int l,r; ll tag; }f[M]; //若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。 //若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。 int n,m,t,l,r,pos[N]; char s[5]; ll c,d[N],a[N]; void add(int l,int r,int c) { int pl=pos[l],pr=pos[r]; for(int i=pl;i<=pr;i++) f[i].tag+=c; if(l!=f[pl].l) { for(int i=f[pl].l;i<l;i++) d[i]-=c; for(int i=f[pl].l;i<=f[pl].r;i++) a[i]=d[i]; sort(a+f[pl].l,a+f[pl].r+1); } if(r!=f[pr].r) { for(int i=r+1;i<=f[pr].r;i++) d[i]-=c; for(int i=f[pr].l;i<=f[pr].r;i++) a[i]=d[i]; sort(a+f[pr].l,a+f[pr].r+1); } } int get(int l,int r,ll c) { int ans=0; int pl=pos[l],pr=pos[r]; for(int i=pl;i<=pr;i++) { int p=lower_bound(a+f[i].l,a+f[i].r+1,c-f[i].tag)-a; ans+=f[i].r+1-p; } for(int i=f[pl].l;i<l;i++) if(d[i]+f[pl].tag>=c) ans--; for(int i=r+1;i<=f[pr].r;i++) if(d[i]+f[pr].tag>=c) ans--; return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&d[i]),a[i]=d[i]; t=sqrt(n); for(int i=1;i<=t;i++) f[i].l=(i-1)*t+1,f[i].r=i*t; if(f[t].r<n) f[++t].r=n,f[t].l=f[t-1].r+1; for(int i=1;i<=t;i++) { sort(a+f[i].l,a+f[i].r+1); for(int j=f[i].l;j<=f[i].r;j++) pos[j]=i; } while(m--) { scanf("%s%d%d%lld",s,&l,&r,&c); if(s[0]==‘M‘) add(l,r,c); else printf("%d ",get(l,r,c)); } return 0; }
以上是关于教主的魔法(分块模板)的主要内容,如果未能解决你的问题,请参考以下文章