题意:给你N个数,有M个操作,操作有两类,(1)"0 l r",表示将区间[l,r]里的每个数都开根号。(2)"1 l r",表示查询区间[l,r]里所有数的和。
虽然题目给出的数的范围达到了2^63次方,但是,最多开根号7次就会变成1。所以在每次更新的时候,判断,如果这个区间里的所有数被开根号的次数大于7,就不用再往下更新了,其次,因为每个数最多只会有7次开根号,所以在更新的时,可以一直更新到叶子结点。
#include
#include
#include
#include
using namespace std;
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int N=100005;
typedef long long LL;
struct node
{
int lft,rht;
LL cnt,sum;
int mid(){return MID(lft,rht);}
int len(){return rht-lft+1;}
};
int n,m;
LL y[N];
struct Segtree
{
node tree[N*4];
void up(int ind)
{
tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
if(tree[LL(ind)].cnt>=7&&tree[RR(ind)].cnt>=7)
tree[ind].cnt=7;
}
void build(int lft,int rht,int ind)
{
tree[ind].lft=lft; tree[ind].rht=rht;
tree[ind].cnt=0; tree[ind].sum=0;
if(lft==rht) tree[ind].sum=y[lft];
else
{
int mid=tree[ind].mid();
build(lft,mid,LL(ind));
build(mid+1,rht,RR(ind));
tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
}
}
void updata(int st,int ed,int ind)
{
if(tree[ind].cnt>=7)
{
tree[ind].sum=tree[ind].len();
return;
}
int lft=tree[ind].lft,rht=tree[ind].rht;
if(st<=lft&&rht<=ed)
{
tree[ind].cnt+=1;
if(lft==rht)
tree[ind].sum=(int)sqrt(tree[ind].sum*1.0);
else
{
updata(st,ed,LL(ind));
updata(st,ed,RR(ind));
up(ind);
}
}
else
{
int mid=tree[ind].mid();
if(st<=mid) updata(st,ed,LL(ind));
if(ed> mid) updata(st,ed,RR(ind));
up(ind);
}
}
LL query(int st,int ed,int ind)
{
int lft=tree[ind].lft,rht=tree[ind].rht;
if(st<=lft&&rht<=ed) return tree[ind].sum;
else
{
int mid=tree[ind].mid();
LL sum1=0,sum2=0;
if(st<=mid) sum1=query(st,ed,LL(ind));
if(ed> mid) sum2=query(st,ed,RR(ind));
return sum1+sum2;
}
}
}seg;
int main()
{
int t_cnt=0;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%I64d\n",&y[i]);
scanf("%d",&m);
seg.build(1,n,1);
printf("Case #%d:\n",++t_cnt);
for(int i=0;ic) swap(b,c);
if(a==0) seg.updata(b,c,1);
else printf("%I64d\n",seg.query(b,c,1));
}
puts("");
}
return 0;
}