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";
}
}
时间会刺破青春表面的彩饰,会在美人的额上掘深沟浅槽;会吃掉稀世之珍!天生丽质,什么都逃不过他那横扫的镰刀。
博主写的那么好,就不打赏一下么(打赏在右边)