题目大意:给出一串数字,两种操作:每次给出一个区间,将区间内的数字全部开根号;区间内的数字求和。
不用区间更新,每次只用单点更新即可,判断区间长度是否等于区间和,如果是就不再更新了,这样相当于每次开根号的时候是将不是全一的区间做了单点更新,其实复杂度并不高。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int N=1000005;
long long int tree[N*4];
long long int num[N];
long long int ans=0;
void build(int l,int r,int i)
{
if(l==r)
{
tree[i]=num[l];
return ;
}
int mid=(l+r)/2;
build(l,mid,i*2);
build(mid+1,r,i*2+1);
tree[i]=tree[i*2+1]+tree[i*2];
}
void updata(int l,int r,int L,int R,int i)
{
//printf("%d\n",i);
if(tree[i]==(r-l+1))
return ;
if(l==r)
{
tree[i]=sqrt(tree[i]);
return ;
}
int mid=(l+r)/2;
if(L<=mid)
updata(l,mid,L,R,i*2);
if(R>mid)
updata(mid+1,r,L,R,i*2+1);
tree[i]=tree[i*2+1]+tree[i*2];
}
void query(int l,int r,int L,int R,int i)
{
if(l>=L&&r<=R)
{
ans+=tree[i];
return ;
}
int mid=(l+r)/2;
if(L<=mid)
query(l,mid,L,R,i*2);
if(R>mid)
query(mid+1,r,L,R,i*2+1);
}
int main()
{
int n;
int ca=1;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%lld",&num[i]);
build(1,n,1);
int q;
scanf("%d",&q);
printf("Case #%d:\n",ca++);
while(q--)
{
int sym,l,r;
scanf("%d %d %d",&sym,&l,&r);
if(l>r)
swap(l,r);
if(sym==0)
{
updata(1,n,l,r,1);
}
if(sym==1)
{
ans=0;
query(1,n,l,r,1);
printf("%lld\n",ans);
}
}
printf("\n");
}
return 0;
}