1.题目链接。题意简洁,就是两种操作,区间整体开方,区间求和。类似于区间修改操作但是我们没必要再加上懒惰标记,因为开方开多了这个点就会变成1,所以其实连续对区间操作,没有几次就不用进行修改了,我们特判一下区间都是1的情况,这样就直接修改不加懒惰标记也是可以的。
#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<math.h>
#define ll long long
#pragma warning(disable:4996)
using namespace std;
const int MAXN = 5000100;
ll a[MAXN];
struct Node
{
int l, r;
ll sum;
}seg[MAXN * 3];
void build(int i, int l, int r)
{
seg[i].l = l;
seg[i].r = r;
if (l == r)
{
seg[i].sum= a[l];
return;
}
int mid = ((l + r) >> 1);
build(i << 1, l, mid);
build((i << 1) | 1, mid + 1, r);
seg[i].sum = seg[i << 1].sum + seg[(i << 1) | 1].sum;
}
void update(int i, int l, int r)
{
if (seg[i].l == l && seg[i].r == r && seg[i].sum == r - l + 1) return;
if (seg[i].l == seg[i].r)
{
seg[i].sum = sqrt(seg[i].sum*1.0);
return;
}
int mid = ((seg[i].l + seg[i].r) >> 1);
if (r <= mid) update(i << 1, l, r);
else if (l > mid) update((i << 1) | 1, l, r);
else
{
update(i << 1, l, mid);
update((i << 1) | 1, mid + 1, r);
}
seg[i].sum = seg[i << 1].sum + seg[(i << 1) | 1].sum;
}
long long SUM(int i, int l, int r)
{
if (l == seg[i].l && r == seg[i].r) return seg[i].sum;
int mid = ((seg[i].l + seg[i].r) / 2);
long long ans = 0;
if (r <= mid) ans = SUM(i << 1, l, r);
else if (l > mid) ans = SUM((i << 1) | 1, l, r);
else
{
ans += SUM(i << 1, l, mid);
ans += SUM((i << 1) | 1, mid + 1, r);
}
return ans;
}
int main()
{
int n;
int T, X, Y;
int iCase = 0;
int M;
while (scanf("%d", &n) != EOF)
{
iCase++;
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
build(1, 1, n);
scanf("%d", &M);
printf("Case #%d:\n", iCase);
while (M--)
{
scanf("%d%d%d", &T, &X, &Y);
if (X > Y)swap(X, Y);
if (T == 0) update(1, X, Y);
else printf("%I64d\n", SUM(1, X, Y));
}
printf("\n");
}
return 0;
}