反思总结,总是学不全,(虽然才学了两天)
这次又学到了,如何用update进行单点更新,这次我们是没有办法进行区间更新了,既然这样在update中,是有限制范围的,因此保证了l==r的时候rt节点一定在所求区间之内,我们此时更新这个结点就行了。。就是简单的单点更新而已,不过是我忘了。。。。。。。
还有一个优化,当sum[rt] == r - l + 1的时候,已经没有可以继续优化的情况了,此时直接return即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
int n, m;
ll sum[100005 << 2];
void pushup(int rt)
{
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int l, int r, int rt)
{
if(l == r)
{
scanf("%I64d", &sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int left, int right, int l, int r, int rt)
{
if(l == r)
{
sum[rt] = (ll)sqrt(sum[rt]);
return ;
}
if(left <= l && right >= r && sum[rt] == r - l + 1)
{
return ;
}
int m = (l + r) >> 1;
if(left <= m) update(left, right, l, m, rt << 1);
if(right > m) update(left, right, m + 1, r, rt << 1 | 1);
pushup(rt);
}
ll query(int left, int right, int l, int r, int rt)
{
if(left <= l && right >= r)
{
return sum[rt];
}
ll ans = 0;
int m = (l + r) >> 1;
if(left <= m) ans += query(left, right, l, m, rt << 1);
if(right > m) ans += query(left, right, m + 1, r, rt << 1 | 1);
return ans;
}
int main()
{
int cas = 0;
while(scanf("%d", &n) != EOF)
{
build(1, n, 1);
scanf("%d", &m);
printf("Case #%d:\n", ++ cas);
while(m --)
{
int tmp;
scanf("%d", &tmp);
int a, b;
scanf("%d%d", &a, &b);
if(a > b) swap(a, b);
if(tmp)
printf("%I64d\n", query(a, b, 1, n, 1));
else
update(a, b, 1, n, 1);
}
printf("\n");
}
return 0;
}