首页 > 其他 > 详细

LibreOJ #6278

时间:2020-09-09 21:48:12      阅读:91      评论:0      收藏:0      [点我收藏+]

题目链接:#6278. 数列分块入门 2

题目大意

给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的元素个数。

solution

我们对每个块进行操作,对于每个块排序

修改操作:对于整块我们记录一下加的之即可,顺序没有改变,然后对于不足整块,我们直接加和然后排序

查询操作:对于整块我们 lower_bound 查找即可, 然后对于不足整块, 我们直接枚举查找

Code:

/**
*    Author: Alieme
*    Data: 2020.9.8
*    Problem: LibreOJ #6278
*    Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>

#define int long long
#define rr register

#define inf 1e9
#define MAXN 100010

using namespace std;

inline int read() {
	int s = 0, f = 0;
	char ch = getchar();
	while (!isdigit(ch)) f |= ch == ‘-‘, ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

void print(int x) {
	if (x < 0) putchar(‘-‘), x = -x;
	if (x > 9) print(x / 10);
	putchar(x % 10 + 48);
}

int n, len;

int a[MAXN], b[MAXN], id[MAXN], v[MAXN];

inline void update(int x) {
	int l = (x - 1) * len + 1, r = min(x * len, n);
	for (rr int i = l; i <= r; i++) b[i] = a[i];
	sort(b + l, b + r + 1);
}

inline void add(int l, int r, int x) {
	int start = id[l], end = id[r];
	if (start == end) {
		for (rr int i = l; i <= r; i++) a[i] += x;
		update(id[l]);
		return ;
	}
	for (rr int i = l; id[i] == start; i++) a[i] += x; update(start);
	for (rr int i = start + 1; i < end; i++) v[i] += x;
	for (rr int i = r; id[i] == end; i--) a[i] += x; update(end);
}

inline int fin(int pid, int x) {
	int l = (pid - 1) * len + 1, r = min(pid * len, n);
	return lower_bound(b + l, b + r + 1, x - v[pid]) - (b + l);
}

inline int query(int l, int r, int x) {
	int ans = 0, start = id[l], end = id[r];
	if (start == end) {
		for (rr int i = l; i <= r; i++) if (a[i] + v[start] < x) ans++;
		return ans;
	}
	for (rr int i = l; id[i] == start; i++) if (a[i] + v[id[i]] < x) ans++;
	for (rr int i = start + 1; i < end; i++) ans += fin(i, x);
	for (rr int i = r; id[i] == end; i--) if (a[i] + v[id[i]] < x) ans++;
	return ans;
}

signed main() {
	// freopen("a1.in", "r", stdin);
	// freopen("a.out", "w", stdout);
	n = read();
	len = sqrt(n);
	for (rr int i = 1; i <= n; i++) a[i] = read(), id[i] = (i - 1) / len + 1;
	for (rr int i = len; i <= n; i += len) update(id[i]);
	for (rr int i = 1; i <= n; i++) {
		int opt = read(), l = read(), r = read(), c = read();
		if (opt == 0) add(l, r, c);
		if (opt == 1) cout << query(l, r, c * c) << "\n";
	}
}

LibreOJ #6278

原文:https://www.cnblogs.com/lieberdq/p/13641810.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!