GSS4 - Can you answer these queries IV

Description

You are given a sequence A of N(N <= 100,000) positive integers. There sum will be less than 10 ^{18}
18
. On this sequence you have to apply M (M <= 100,000) operations:

(A) For given x,y, for each elements between the x-th and the y-th ones (inclusively, counting from 1), modify it to its positive square root (rounded down to the nearest integer).

(B) For given x,y, query the sum of all the elements between the x-th and the y-th ones (inclusively, counting from 1) in the sequence.

Solution

因为每个数至多被修改6遍就能变成1, 因此暴力修改最多$6n$次, 为了保证最多修改6次, 当最大值等于1的时候不修改.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
const long long N = 100005;
using std:: max;
using std:: min;
long long Read() {
long long x = 0;char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) {
x = x * 10ll + c -'0';
c = getchar();
}
return x;
}
struct Node {
long long v, val;
Node *ls, *rs;
int l, r;
Node () { v = val = 0, ls = rs = NULL; }
void merge() { v = ls->v + rs->v, val = max(ls->val, rs->val); }
void init(long long _) { v = val = _; }
void Sqrt() { v = val = sqrt(val); }
void clear() { if (ls) ls->clear(), rs->clear(); delete this; }
};
#define new_Node() new Node()
template <typename T>
class Tree {
Node *root; int n;
public:
Tree () { root = new_Node(); }
void clear() { root->clear(); }
void build(int l, int r, Node *node, long long *a) {
node->l = l, node->r = r;
if (l == r) return node->init(a[l]);
int mid = l + r >> 1;
node->ls = new_Node(); node->rs = new_Node();
build(l, mid, node->ls, a);
build(mid + 1, r, node->rs, a);
node->merge();
}
void Build(int _, long long *a) { return n = _, build(1, n, root, a); }
void modify(int L, int R, Node *node) {
if (node->val < 2) return ;
int l = node->l, r = node->r;
if (l == r) return node->Sqrt();
int mid = l + r >> 1;
if (L <= mid) modify(L, R, node->ls);
if (R > mid) modify(L, R, node->rs);
node->merge();
}
void Modify(int L, int R) {
if (R < L) std:: swap(L, R);
L = max(L, 1),
R = min(R, n);
modify(L, R, root);
}
long long query(int L, int R, Node *node) {
int l = node->l, r = node->r;
if (l >= L and r <= R) return node->v;
int mid = l + r >> 1;
long long res = 0;
if (L <= mid) res += query(L, R, node->ls);
if (R > mid) res += query(L, R, node->rs);
return res;
}
long long Query(int L, int R) {
if (R < L) std:: swap(L, R);
L = max(L, 1),
R = min(R, n);
return query(L, R, root);
}
};
long long S[N];
int main () {
int n, t = 1;
Tree<Node>* T;
while (~scanf("%d", &n)) {
printf("Case #%d:\n", t);
for (long long i = 1; i <= n; i += 1)
S[i] = Read();
T = new Tree<Node>();
T->Build(n, S);
int m; scanf("%d", &m);
while (m --) {
int opt, l, r;
scanf("%d%d%d", &opt, &l, &r);
if (not opt) T->Modify(l, r);
if (opt == 1) printf("%lld\n", T->Query(l, r));
}
puts(""); t += 1;
T->clear(); delete T; T = NULL;
}
return 0;
}
-------------本文结束感谢您的阅读-------------