题意
首先给出一个数字n代表,然后又n个数据。
再给出一个数字k,代表n次查询,查询分为两种:
0 x y:将 [x,y ]区间的每个数字开根号
1 x y:=求[x,y ]区间和,并输出
样例
Sample Input
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
Sample Output
Case #1:
19
7
6
AC代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include<iostream>
using namespace std;
const int MAX = 100102;
typedef long long LL;
LL tree[MAX], a[MAX];
int n,m,t,x,y;
int lowbit(int x)
{
return x&(-x);
}
void update(int x, LL val)
{
for(int i=x; i<=n; i += lowbit(i))
tree[i] += val;
}
LL getsum(int x)
{
LL sum = 0;
for(int i=x; i>0;i -= lowbit(i))
sum += tree[i];
return sum;
}
int main()
{
//freopen("a.txt","r",stdin);
int count = 1;
while(~scanf("%d",&n)) //等价于while(scanf("%d",&n)!=EOF)
{
memset(tree, 0, sizeof(tree) );
for(int i=1; i<=n; ++i)
{
scanf("%I64d", &a[i]);
update(i, a[i]); //创建树状数组
}
scanf("%d",&m);
printf("Case #%d:\n",count++);
while(m--)
{
cin>>t>>x>>y;
if(x>y)
swap(x,y);
if(t==0)
{
if(getsum(y) - getsum(x-1) <= y - x + 1) 如果区间内的所有数都是1则不必更新
continue;
else
{
for(int j=x; j<=y; j++)
{
if(a[j] <= 1) ///这里如果写成“if(a[j]==1)” ,也能通过
continue;
update(j, -a[j]);
a[j] = (LL)sqrt(a[j]); //进行开方,注意数据类型要转换一下
update(j,a[j]); //更新树状数组
}
}
}
else
{
LL ans = getsum(y) - getsum(x-1);
printf("%I64d\n",ans);
}
}
cout<<endl;
}
return 0;
}
题源:acm.hdu.edu.cn/showproblem…