有n艘战舰,每艘战舰的防护罩都有一定的能量,我军有秘密武器,每轰一次,一个区间内的战舰防护罩将为原来能量的开方,查询的则是这个区间内战舰防护罩的能量之和。
要注意的是,区间的两边的边界值输入时大小是不确定的
#include
#include
#include
#include
using namespace std;
const int L = 100000+10;
__int64 sum[L<<2],cnt[L<<2];
void add(int i)
{
sum[i] = sum[2*i]+sum[2*i+1];
cnt[i] = cnt[2*i]&&cnt[2*i+1];
}
void init(int l,int r,int i)
{
if(l == r)
{
scanf("%I64d",&sum[i]);
return;
}
int mid = (l+r)>>1;
init(l,mid,2*i);
init(mid+1,r,2*i+1);
add(i);
}
void insert(int L,int R,int l,int r,int i)
{
if(l == r)
{
sum[i] = sqrt(sum[i]);//向下取整
if(sum[i]<=1)//如果为0,则标记不能再访问了
cnt[i] = 1;
return ;
}
int mid = (l+r)>>1;
if(L<=mid && !cnt[2*i])//孩子已经破坏了则不需再访问
insert(L,R,l,mid,2*i);
if(R>mid && !cnt[2*i+1])
insert(L,R,mid+1,r,2*i+1);
add(i);
}
__int64 query(int L,int R,int l,int r,int i)//查询区间和
{
if(L<=l && r<=R)
return sum[i];
int mid = (l+r)>>1;
__int64 ans = 0;
if(L<=mid)
ans+=query(L,R,l,mid,2*i);
if(R>mid)
ans+=query(L,R,mid+1,r,2*i+1);
return ans;
}
int main()
{
int n,m,i,j,x,l,r,cas = 1,flag;
while(~scanf("%d",&n))
{
memset(sum,0,sizeof(sum));
memset(cnt,0,sizeof(cnt));
init(1,n,1);
printf("Case #%d:\n",cas++);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&flag,&l,&r);
if(l>r)//这里要注意
swap(l,r);
if(flag)
printf("%I64d\n",query(l,r,1,n,1));
else
insert(l,r,1,n,1);
}
printf("\n");
}
return 0;
}