题意:给一个数组序列, 数组长度为100000,现在有两种操作, 一种操作是将某一个固定区间所有数开方(向下取整),另一种操作是询问某个区间的所有数字之和。
一句话题解:
每个数最多才能被开方八次,所以对于长度为n的数组,开方的次数最多为8*n。因为是向下取整,所以节约时间的方
法主要是处理被开方数为1的情况。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define maxn 100100
#define lson l, m, root*2
#define rson m+1, r, root*2+1
int lazy[maxn<<2];
long long tree[maxn<<2];
void pushup(int root)
{
tree[root] = tree[root*2] + tree[root*2+1];
lazy[root] = lazy[root*2]&&lazy[root*2+1];
}
void build(int l, int r, int root)
{
lazy[root] = 0;
if(l == r)
{
scanf("%lld", &tree[root]);
return ;
}
int m = (l + r) / 2;
build(lson);
build(rson);
pushup(root);
}
long long query(int a, int b, int l, int r, int root)
{
if(a <= l && b >= r)
return tree[root];
int m = (l + r) / 2;
long long ret = 0;
if(a <= m)
ret += query(a, b, lson);
if(b > m)
ret += query(a, b, rson);
return ret;
}
void update(int a, int b, int l, int r, int root)
{
if(l == r)
{
tree[root] = sqrt(tree[root]);
if(tree[root] <= 1)
lazy[root] = 1;
return ;
}
int m = (l + r) / 2;
if(a <= m && !lazy[root])
update(a, b, lson);
if(b > m && ! lazy[root])
update(a, b, rson);
pushup(root);
}
int main()
{
int n, cnt = 1;
while(scanf("%d", &n) != EOF)
{
build(1, n, 1);
int m;
scanf("%d", &m);
int flag = 1;
while(m--)
{
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
if(x > y)
x^=y^=x^=y;
if(t == 0)
update(x, y, 1, n, 1);
else
{
if(flag)
{
printf("Case #%d:\n",cnt);
flag = 0;
}
printf("%lld\n", query(x, y, 1, n, 1));
}
}
cnt++;
printf("\n");
}
return 0;
}