Skip to content

Commit 06cc597

Browse files
Add files via upload
1 parent 4046d5e commit 06cc597

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
2+
Square root is a function that converges quite rapidly.
3+
4+
10^18 ---- 10^9 --- 10^5 --- 10^3 ---400 -- 20 --4 -- 2
5+
6+
About 7-8 times at most. Everything become 1 after that.
7+
8+
We can't use lazy propagation because the function is complicated.
9+
10+
Maintain a max segment tree, and if the maximum of a segment is 1, then ignore it. Taking the square root will not change anything.
11+
12+
Otherwise perform the update one by one for each element.
13+
14+
In the worst case, we will perform 8 O(n) scans, which is perfectly fine !
15+
16+
Note - When scanf reads EOF, it returns -1 or 0 ... I made a mistake there.
17+
18+
Also, in this question (x, y) are not necessarily sorted. They must be swapped, if x > y.
19+
20+
------------------------------------------------------------------------------------------------
21+
22+
long long square_root(long long n)
23+
{
24+
long long left = 1, right = 1e9;
25+
26+
while(left <= right)
27+
{
28+
long long mid = (left + right) >> 1;
29+
30+
if(square(mid) <= n)
31+
{
32+
if(square(mid + 1) > n)
33+
{
34+
return mid;
35+
}
36+
else
37+
{
38+
left = mid + 1;
39+
}
40+
}
41+
else
42+
{
43+
right = mid;
44+
}
45+
}
46+
}
47+
48+
void build(int n, int left, int right)
49+
{
50+
if(left == right)
51+
{
52+
sum_tree[n] = max_tree[n] = A[left];
53+
return;
54+
}
55+
56+
int mid = (left + right) >> 1;
57+
build(LEFT(n), left, mid);
58+
build(RIGHT(n), mid + 1, right);
59+
60+
max_tree[n] = max(max_tree[LEFT(n)], max_tree[RIGHT(n)]);
61+
sum_tree[n] = sum_tree[LEFT(n)] + sum_tree[RIGHT(n)];
62+
}
63+
64+
void update(int n, int left, int right, int query_left, int query_right)
65+
{
66+
if(query_right < left || right < query_left || max_tree[n] == 1)
67+
return;
68+
69+
if(left == right)
70+
{
71+
A[left] = square_root(A[left]);
72+
sum_tree[n] = max_tree[n] = A[left]; //printf("A[%d] is now %lld\n", left, A[left]);
73+
return;
74+
}
75+
76+
int mid = (left + right) >> 1;
77+
update(LEFT(n), left, mid, query_left, query_right);
78+
update(RIGHT(n), mid + 1, right, query_left, query_right);
79+
80+
sum_tree[n] = sum_tree[LEFT(n)] + sum_tree[RIGHT(n)];
81+
max_tree[n] = max(max_tree[LEFT(n)], max_tree[RIGHT(n)]); //printf("S[%d] = %lld\n", n, sum_tree[n]);
82+
}
83+
84+
long long sum(int n, int left, int right, int query_left, int query_right)
85+
{
86+
if(query_right < left || right < query_left)
87+
return 0;
88+
89+
if(query_left <= left && right <= query_right)
90+
return sum_tree[n];
91+
92+
int mid = (left + right) >> 1;
93+
long long left_sum = sum(LEFT(n), left, mid, query_left, query_right);
94+
long long right_sum = sum(RIGHT(n), mid + 1, right, query_left, query_right);
95+
96+
return (left_sum + right_sum);
97+
}
98+
99+
void solve(int no_of_elements)
100+
{
101+
for(int i = 1; i <= no_of_elements; i++)
102+
scanf("%lld", &A[i]);
103+
104+
memset(max_tree, 0, sizeof(max_tree));
105+
memset(sum_tree, 0, sizeof(sum_tree));
106+
build(1, 1, no_of_elements);
107+
108+
int no_of_queries;
109+
scanf("%d", &no_of_queries);
110+
111+
while(no_of_queries--)
112+
{
113+
const int SUM = 1, UPDATE = 0;
114+
int query_type, left, right;
115+
scanf("%d %d %d", &query_type, &left, &right);
116+
117+
if(left > right) swap(left, right);
118+
119+
if(query_type == SUM)
120+
{
121+
long long answer_sum = sum(1, 1, no_of_elements, left, right);
122+
printf("%lld\n", answer_sum);
123+
}
124+
if(query_type == UPDATE)
125+
{
126+
update(1, 1, no_of_elements, left, right);
127+
}
128+
}
129+
printf("\n");
130+
}
131+
132+
int main()
133+
{
134+
for(int i = 1; ; i++)
135+
{
136+
int no_of_elements;
137+
138+
if(scanf("%d", &no_of_elements) < 1)
139+
break;
140+
141+
printf("Case #%d:\n", i);
142+
solve(no_of_elements);
143+
}
144+
145+
return 0;
146+
}

0 commit comments

Comments
 (0)