P2801 教主的魔法


P2801 教主的魔法

洛谷题解

#include
#include
#include
#include
#include
#define long long int
using namespace std;
int a[1000005],d[1000005],block,n,q,x,y,z,lf[1000005],rg[1000005],num,belong[1000005],tag[1000005];
char op[3];
void build(){
  block = sqrt(n);
  num = n / block;
  if(n % block) num++;
  for(int i = 1; i <= num; i++){
    lf[i] = (i - 1) * block + 1, rg[i] = i * block;
  }//循环里写的sort
  rg[num] = n;
  for(int i = 1; i <= n; i++)
    belong[i] = (i - 1)/block + 1;
  for(int i = 1; i <= num; i++)
  	sort(d + lf[i], d + rg[i] + 1);//每一段都进行排序
}
void add(int l, int r, int val){
  int st = belong[l], ed = belong[r];
  if(st == ed){
    for(int i = l; i <= r; i++)
      a[i] += val;
    for(int i = lf[st]; i <= rg[st]; i++) d[i] = a[i];
    sort(d + lf[st], d + rg[st] + 1);
    return;
  }
  if(l != lf[st]){
    for(int i = l; i <= rg[st]; i++) a[i] += val;
    for(int i = lf[st]; i <= rg[st]; i++) d[i] = a[i];
    sort(d + lf[st], d + rg[st] + 1);
    st++;
  }
  if(r != rg[ed]){
    for(int i = lf[ed]; i <= r; i++) a[i] += val;
    for(int i = lf[ed]; i <= rg[ed]; i++) d[i] = a[i];
    sort(d + lf[ed], d + rg[ed] + 1);
    ed--;
  }
  for(int i = st; i <= ed; i++) tag[i] += val;//+=
}
int query(int l, int r, int c){
  int ans = 0, st = belong[l], ed = belong[r];
  if(st == ed){
    for(int i = l; i <= r; i++)
      if(a[i] + tag[st] >= c) ans++;
    return ans;
  }
  if(l != lf[st]){
    for(int i = l ; i <= rg[st]; i++)
      if(a[i] + tag[st] >= c) ans++;//error:without tag
    st++;
  }
  if(r != rg[ed]){
    for(int i = lf[ed] ; i <= r; i++)
      if(a[i] + tag[ed] >= c) ans++;//error:without tag
    ed--;
  }
  for(int i = st; i <= ed; i++){
  	if(c >  d[rg[i]] + tag[i] ) continue;//如果这一块最大的值都小于c,则continue
  	int id = lower_bound(d + lf[i], d + rg[i], c - tag[i]) - d;
    ans += rg[i] - id + 1;
  }
  return ans;
}
signed main(){
  scanf("%d%d",&n,&q);
  for(int i = 1; i <= n; i++){
    scanf("%d",&a[i]);//原数组
    d[i] = a[i];//排序数组
  }
  build();
  for(int i = 1; i <= q; i++){
	  scanf("%s%d%d%d",op,&x,&y,&z);
	  if(op[0] == 'M'){
	    add(x,y,z);
	  }else if(op[0] == 'A'){
	    printf("%d\n", query(x,y,z));
	  }
  }
  return 0;
}