这个题乍一看没思路啊,但后来发现每个数小于2^63,开方至多6次就变成1了,然后就不用开方了,只有这么暴力了。
(似乎我的代码里有一些没用的东西= =)
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int MAXN = 100000;
int n;
LL A[MAXN + 10];
struct seg {
int l, r;
LL sum;
inline int length() {
return r - l + 1;
}
void update(seg &lch, seg &rch) {
if(l < r) sum = lch.sum + rch.sum;
}
} Tree[MAXN * 4 + 10];
void Build(int u, int l, int r) {
seg &cur = Tree[u];
cur.l = l, cur.r = r;
if(l >= r) cur.sum = A[l];
else {
int mid = (l + r) / 2;
Build(u * 2, l, mid);
Build(u * 2 + 1, mid + 1, r);
cur.update(Tree[u * 2], Tree[u * 2 + 1]);
}
}
void Ins(int u, int l, int r) {
seg &cur = Tree[u], &lch = Tree[u * 2], &rch = Tree[u * 2 + 1];
if(cur.r < l || cur.l > r) return ;
else {
if(l <= cur.l && cur.r <= r && cur.length() == cur.sum) return ;
else if(cur.l >= cur.r) cur.sum = sqrt(cur.sum + 0.5);
else Ins(u * 2, l, r), Ins(u * 2 + 1, l, r);
}
cur.update(lch, rch);
}
LL Query(int u, int l, int r) {
seg &cur = Tree[u];
if(cur.r < l || cur.l > r) return 0;
else if(l <= cur.l && cur.r <= r) return cur.sum;
else return Query(u * 2, l, r) + Query(u * 2 + 1, l, r);
}
int main() {
int kase = 0;
while(scanf("%d", &n) == 1 && n) {
for(int i = 1; i <= n; i++)
scanf("%I64d", &A[i]);
Build(1, 1, n);
int ops, opt, l, r;
scanf("%d", &ops);
printf("Case #%d:\n", ++kase);
for(int i = 1; i <= ops; i++) {
scanf("%d%d%d", &opt, &l, &r);
if(l > r) swap(l, r);
if(opt) printf("%I64d\n", Query(1, l, r));
else Ins(1, l, r);
}
puts("");
}
return 0;
}