教主的魔法

题目大意

给定一个数列,支持区间加法,求区间大于等于 \(c\) 的数的个数

思路

分块裸题
散的个体单独加,询问时单独判
对于一整块加则打上标记
要求块中大于等于 \(c\) 的数的个数
我们不妨将块中元素排序,二分求解即可
为了保证时间复杂度
我们在修改的时候排序
因为同时加一个数,相对大小不变,不需排序
那么我们只有排暴力更改的散的个体所在的块就可以了
时间复杂度 \(O(n\sqrt n\log n)\)

\(Code\)

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

const int N = 1e6 + 5;
int n , m , a[N] , t[N] , belong[N] , st[N] , ed[N] , tag[N] , num; 

inline int read()
{
	int res = 0;
	char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9') res = res * 10 + ch - '0' , ch = getchar();
	return res;
}

inline void Sort(int x)
{
	for(register int i = st[x]; i <= ed[x]; i++) t[i] = a[i];
	sort(t + st[x] , t + ed[x] + 1);
}

inline void prepare()
{
	num = (int)sqrt(n);
	for(register int i = 1; i <= num; i++) st[i] = n / num * (i - 1) + 1 , ed[i] = n / num * i;
	ed[num] = n;
	for(register int i = 1; i <= num; i++)
	{
		for(register int j = st[i]; j <= ed[i]; j++) belong[j] = i;
		Sort(i);
	}
}

inline void change(int l , int r , int c)
{
	int x = belong[l] , y = belong[r];
	if (x == y)
	{
		for(register int i = l; i <= r; i++) a[i] += c;
		Sort(x);
		return;
	}
	for(register int i = l; i <= ed[x]; i++) a[i] += c;
	for(register int i = st[y]; i <= r; i++) a[i] += c;
	for(register int i = x + 1; i <= y - 1; i++) tag[i] += c;
	Sort(x) , Sort(y);
}

inline int query(int l , int r , int c)
{
	int x = belong[l] , y = belong[r] , res = 0;
	if (x == y)
	{
		for(register int i = l; i <= r; i++) 
		if (a[i] + tag[x] >= c) res++;
		return res;
	}
	for(register int i = l; i <= ed[x]; i++) 
	if (a[i] + tag[x] >= c) res++;
	for(register int i = st[y]; i <= r; i++)
	if (a[i] + tag[y] >= c) res++;
	for(register int i = x + 1; i <= y - 1; i++)
		res += ed[i] - (lower_bound(t + st[i] , t + ed[i] + 1 , c - tag[i]) - t) + 1;
	return res;
}

int main()
{
	n = read() , m = read();
	for(register int i = 1; i <= n; i++) a[i] = read();
	prepare();
	char opt[2];
	int x , y , z;
	for(register int i = 1; i <= m; i++)
	{
		scanf("%s" , opt);
		x = read() , y = read() , z = read();
		if (opt[0] == 'A') printf("%d\n" , query(x , y , z));
		else change(x , y , z);
	}
}
posted @ 2020-08-01 16:57  leiyuanze  阅读(85)  评论(0编辑  收藏  举报