LibreOJ #6281

题目链接:#6281. 数列分块入门 5

题目大意

给出一个长为 \(n\) 的数列 \(a_1, a_2, ..., a_m\) ,以及 \(n\) 个操作,操作涉及区间开方,区间求和。

solution

对于这道题我们发现, 一个数最多被开方 \(5\) 次, \(5\) 次之后所有的数就都变成了 \(1\)\(0\)

所以我们的操作是这样的:

修改操作: 我们对整块打个标记,如果该块全部无法在开根了,我们在整块操作时就不用管了,然后直接暴力开根整块即可,对于散块,我们也是直接暴力开根加和即可

查询操作: 我们对于散块直接加,对于整块我们加上总和即可

Code:

/**
*    Author: Alieme
*    Data: 2020.9.8
*    Problem: LibreOJ #6281
*    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], v[MAXN], id[MAXN], sum[MAXN];

bool vis[MAXN];

inline void update(int x) {
	if (vis[x]) return ;
	vis[x] = 1;
	sum[x] = 0;
	for (rr int i = (x - 1) * len + 1; i <= x * len; i++) {
		a[i] = sqrt(a[i]), sum[x] += a[i];
		if (a[i] > 1) vis[x] = 0;
	}
}

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

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

signed main() {
	n = read();
	len = sqrt(n);
	for (rr int i = 1; i <= n; i++) a[i] = read(), id[i] = (i - 1) / len + 1, sum[id[i]] += a[i];
	while (n--) {
		int opt = read(), l = read(), r = read(), c = read();
		if (opt == 0) add(l, r);
		if (opt == 1) cout << query(l, r) << "\n";
	}
}
posted @ 2020-09-09 21:01  Aliemo  阅读(144)  评论(0编辑  收藏  举报