题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4027
由于数据均在63位数的范围之内,因此每个数计算平方根的次数不会超过6次。更新时统计每个区段的更新次数,若>6则不再执行。维护区间和即可。
注意本题有坑,输入时每组数据的x和y可能会是x>y。
来自HDU-Disscuss的数据:
7
81 12 3 7 9 6 26
5
0 3 5
0 3 1
1 1 5
0 2 3
1 1 7
ans:
18
48
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#define ll unsigned long long
using namespace std;
const int maxn=2e5+10;
int n,m;
ll a[maxn];
struct tree{
int left,right,cnt;
ll sum;
}c[maxn<<2];
void build(int id,int l,int r) {
c[id].left = l;
c[id].right = r;
c[id].cnt = 0;
if (l == r) {
c[id].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
}
ll query_sum(int id,int l,int r) {
if (r < c[id].left || l > c[id].right)return 0;
if (c[id].left >= l && c[id].right <= r)
return c[id].sum;
return query_sum(id << 1, l, r) + query_sum(id << 1 | 1, l, r);
}
void update(int id,int l,int r) {
if (c[id].left > r || c[id].right < l)return;
if (c[id].left >= l && c[id].right <= r) {
if (c[id].cnt > 6)return;
c[id].cnt++;
if (c[id].left == c[id].right) {
c[id].sum = (ll) (sqrt(c[id].sum));
return;
}
}
update(id << 1, l, r);
update(id << 1 | 1, l, r);
c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
return;
}
int main() {
int sce = 0;
while (~scanf("%d", &n)) {
++sce;
for (int i = 1; i <= n; ++i)
scanf("%lld", &a[i]);
scanf("%d", &m);
memset(c, 0, sizeof(c));
build(1, 1, n);
int x, y, z;
printf("Case #%d:\n", sce);
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &x, &y, &z);
if (y > z)swap(y, z);
if (x == 0)
update(1, y, z);
else {
printf("%lld\n", query_sum(1, y, z));
}
}
printf("\n");
}
return 0;
}