思路:这道题很坑。
区间开根号加区间求和,开根号,该怎么开,每个点开肯定超时,然后自己拿计算机算了算,long long之内的数据大概开7次根号就成为1了,那先一个一个开根号,然后再剪枝,和等于区间个数时直接return,这样10w个数据开70w次根号,,我运行了一下,只需要3ms就算出来了,所以肯定不会超时。
不过这道题很坑,它输入的l可能会比r大,另外卡cin,cin会tle,取消同步就600ms。。。
#include <bits/stdc++.h>
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define ll long long
#define ld long double
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define lcm(a,b) ((a)*(b)/(__gcd((a),(b))))
#define mod 100003
#define MP make_pair
#define PI pair<int,int>
using namespace std;
const int N = 1e5 + 10;
int n, m;
ll tree[N << 2];
void pushup(int rt) {
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void build(int l, int r, int rt) {
if(l == r) {
cin >> tree[rt];
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int L, int R, int l, int r, int rt) {
if(tree[rt] == (r - l + 1))
return;
if(l == r) {
tree[rt] = sqrt(1.0 * tree[rt]);
return;
}
int m = (l + r) >> 1;
if(L <= m)
update(L, R, l, m, rt << 1);
if(m < R)
update(L, R, m + 1, r, rt << 1 | 1);
pushup(rt);
}
ll query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return tree[rt];
}
int m = (l + r) >> 1;
ll ans = 0;
if(L <= m)
ans += query(L, R, l, m, rt << 1);
if(m < R)
ans += query(L, R, m + 1, r, rt << 1 | 1);
return ans;
}
int main() {
int k = 1;
while(cin >> n) {
cout << "Case #" << k++ << ":" << endl;
build(1, n, 1);
cin >> m;
for(int a, b, c, i = 0; i < m; i++) {
cin >> a >> b >> c;
if(b > c)
swap(b, c);
if(!a) {
update(b, c, 1, n, 1);
} else {
cout << query(b, c, 1, n, 1) << endl;
}
}
cout << endl;
}
return 0;
}