题意:
n列邪恶的战舰的都被排列在一个线前的战斗。我们的指挥官决定使用我们的秘密武器消灭战列舰。
每个战列舰可以标记值的耐力。
我们的秘密武器,每一次的攻击一个区间,它可以使其区间内的战舰耐力降低到原始值的平方根(向下取整)。
求区间和。
思路: 单点更新 区间求和 当叶子为1或0时可以标记不再更新 那么整个区间的叶子全为0 或 1 时 也不用更新 优化时间
注意: 给出的区间可能会使 人 r >l 。
AC code:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
#define N 1000100
struct node
{
LL l;
LL r;
LL sum;
}tree[N << 2];
bool used[N << 2]; //标记数组 表示区间内的值 是否全为0或1
void build(LL root, LL l, LL r)
{
tree[root].l = l;
tree[root].r = r;
if (l == r)
{
scanf("%lld", &tree[root].sum); //节点输入,优化时间(用数组长度较大的时候会TLE)
if (tree[root].sum <= 1) //假如叶子节点的值 为0或1 标记 不再更新它
{
used[root] = true;
}
return;
}
LL mid = (l + r) / 2;
build(root * 2, l, mid);
build(root * 2 + 1, mid + 1, r);
tree[root].sum = tree[root * 2].sum + tree[root * 2 + 1].sum;
if (used[root * 2] && used[root * 2 + 1]) { used[root] = true; } //假如区间内的左右区间内的叶子节点值 全部为0或1 标记不再更新它
}
void update(LL root, LL l, LL r)
{
if (used[root]) return;
LL mid = (tree[root].l + tree[root].r) / 2;
if (tree[root].l == tree[root].r)
{
tree[root].sum = sqrt(tree[root].sum);
if (tree[root].sum <= 1) { used[root] = true; } //假如叶子节点的值更新后 为0或1 标记 不再更新它
return;
}
if (l <= mid && used[root * 2] == false)
{
update(root * 2, l, r);
}
if (r > mid && used[root * 2 + 1] == false)
{
update(root * 2 + 1, l, r);
}
tree[root].sum = tree[root * 2].sum + tree[root * 2 + 1].sum;
if (used[root * 2] && used[root * 2 + 1]) { used[root] = true; } //假如更新后的区间内的左右区间内的叶子节点值 全部为0或1 标记不再更新它
}
LL query(LL root, LL l, LL r)
{
LL ans = 0;
if (l <= tree[root].l && tree[root].r <= r)
{
return tree[root].sum;
}
LL mid = (tree[root].l + tree[root].r) / 2;
if (l <= mid)
{
ans += query(root * 2, l, r);
}
if (r > mid)
{
ans += query(root * 2 + 1, l, r);
}
return ans;
}
int main()
{
LL i, f, x, y, n, m, k = 1;
while (scanf("%lld", &n) != EOF)
{
memset(used, false, sizeof(used));
memset(tree, 0, sizeof(used));
printf("Case #%lld:\n", k++);
build(1, 1, n);
scanf("%lld", &m);
while (m--)
{
scanf("%lld%lld%lld", &f, &x, &y);
if (x > y) { swap(x, y); }
if (!f)
{
update(1, x, y);
}
else
{
printf("%lld\n", query(1, x, y));
}
}
printf("\n");
}
return 0;
}