题意:
给定一个序列和m个操作,
1,让l~r区间内的数都开方
2,求区间和。
思路:
由于LL内的数最多开方10次就会变成1了, 所以用区间维护区间和, 然后开方的时候如果不是全都是1的话就暴力开方, 区间内全都是1的话就不更新。
这么搞不是很靠谱的感觉。。用线段树套平衡树可以做到mlognlogn。。 但是懒得写了。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL long long
#define N 100020
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
int n;
LL sum[N*4];
void push_up(int i) {
sum[i] = sum[ls] + sum[rs];
}
void build(int ll, int rr, int i) {
if(ll == rr) {
scanf("%lld", &sum[i]);
return;
}
build(ll, md, ls);
build(md + 1, rr, rs);
push_up(i);
}
void update(int l, int r, int ll, int rr, int i) {
if(sum[i] == rr - ll + 1)
return;
if(ll == rr) {
sum[i] = sqrt(sum[i] + 0.5);
return;
}
if(r <= md) update(l, r, lson);
else if(l > md) update(l, r, rson);
else
update(l, md, lson),
update(md + 1, r, rson);
push_up(i);
}
LL query(int l, int r, int ll, int rr, int i) {
if(ll == l && rr == r) return sum[i];
if(r <= md) return query(l, r, lson);
if(l > md) return query(l, r, rson);
return query(l, md, lson) + query(md + 1, r, rson);
}
int main() {
int kk = 0;
while(scanf("%d", &n) != EOF) {
build(1, n, 1);
int m;
scanf("%d", &m);
printf("Case #%d:\n", ++kk);
while(m--) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(l > r) swap(l, r);
if(op == 0)
update(l, r, 1, n, 1);
else
printf("%lld\n", query(l, r, 1, n, 1));
}
puts("");
}
return 0;
}