我在尝试此题时遇到了困难,WA40。
查看原帖
我在尝试此题时遇到了困难,WA40。
222865
迟暮天复明心華楼主2021/6/5 15:37

RT

我用分块的方法维护。对于修改操作,使用边界暴力,中间 deltadelta 的做法。每次修改后放到 b 数组里进行排序,之后查询的时候二分查找每一块,边界暴力查找。

感觉思路上没有什么问题。但是具体实现的细节上可能出现了问题。

#include<stdio.h>
#include<algorithm>
#include<math.h>

#define int ll
int n, q, a[100010], belong[100010], b[100010];
int s, c, st[100010], ed[100010], delta[100010];
void pretreat() {
	s = sqrt(n);
	for(int i = 1; i <= n; i += s) st[++c] = i, ed[c] = min(i + s - 1, n);
	rep(i, 1, c) rep(j, st[i], ed[i]) belong[j] = i;
	rep(i, 1, s) std::sort(b + st[i], b + ed[i] + 1);
}
void range_add(int l, int r, int w) {
	ri x = belong[l], y = belong[r];
	if(x == y) {
		rep(i, l, r) a[i] += w;
	  rep(i, 1, n) b[i] = a[i];
	  rep(i, 1, s) std::sort(b + st[i], b + ed[i] + 1);
		return;
	}
	rep(i, l, ed[x]) a[i] += w;
	rep(i, st[y], r) a[i] += w;
	rep(i, 1, n) b[i] = a[i];
	rep(i, 1, s) std::sort(b + st[i], b + ed[i] + 1);
	rep(i, x + 1, y - 1) delta[i] += w;

	return;
}
int range_query(int bl, int w) {
	int l = st[bl], r = ed[bl];
	if(b[r] + delta[bl] < w) return 0;
	while(l < r) {
		int mid = l + r >> 1;
		if(b[mid] + delta[bl] < w) l = mid + 1;
		else r = mid;
	}
	while(b[r] + delta[bl] < w) ++r;
	//printf("%d %d %d %d\n", ed[bl], bl, w, r);
	return (ed[bl] - r + 1);
}
int query(int l, int r, int w) {
	ri x = belong[l], y = belong[r];
	//printf("%d %d\n", x, y);
	if(x == y) {
		int ans = 0;
		rep(i, l, r) if(a[i] + delta[belong[i]] >= w) ++ans;
		return ans;
	}
	int ans = 0;
	rep(i, l, ed[x]) ans += ((a[i] + delta[belong[i]]) >= w);
	rep(i, st[y], r) ans += ((a[i] + delta[belong[i]]) >= w);
	rep(i, x + 1, y - 1) ans += range_query(i, w);
	return ans;
}
signed main() {
	read(n), read(q);
	rep(i, 1, n) read(a[i]), b[i] = a[i];
	pretreat();
	while(q--) {
		int l, r, w;
		char op[1000];
		scanf("%s ", op);
		read(l), read(r), read(w);
		if(op[0] == 'M') range_add(l, r, w);
		else print(query(l, r, w), '\n');
	}
	return 0;
}

IO和预处理均已省略。

2021/6/5 15:37
加载中...