题目大意就是给你n个数,然后进行m次操作,区间更新,然后查询区间和。
这题有点特别,因为更新[l,r]时,不是常规的那种更新例如把[l,r]内的每个数换成v或把[l,r]里的每个数都增加v,而是[l,r]内的每个数都更新为其本身的二分之一次方。这样子的话我们就不能通过使用lazy标记来达到不更新到叶子节点偷懒的目的,因为一个sqrt(segtree[i].sum)不一定等于sqrt(segtree[i*2].sum)+sqrt(segtree[i*2+1].sum),所以每次更新区间都要更新到叶子节点才可以,但是每次更新都更新到叶子结点明显复杂度会很高,所以设了个flag用来标记当前结点是否需要更新,当1.叶子节点为0/1时,更新不更新没什么区别 2.当父节点的2个儿子节点都被标记了则说明该父节点再怎么更新其值也不会变化也所以标记1。那么一但更新到flag为true节点时不用更新了。
ps:这题有一个坑,题目说是更新x和y之间的值和查询x和y之间的值,并没说明谁大谁小,所以判断一下
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
using namespace std;
#define maxn 100010
struct node
{
int l,r;
long long sum;
bool flag;//用来标记该节点是否可以不用更新了 true 表示不用更新了
}segtree[4*maxn];
long long a[maxn];
int n,m;
void pushup(int i)
{
segtree[i].sum=segtree[i<<1].sum+segtree[(i<<1)|1].sum;
}
void build(int i,int l,int r)
{
segtree[i].l=l;
segtree[i].r=r;
segtree[i].flag=false;
if(l==r)
{
segtree[i].sum=a[l];
return ;
}
int mid=(l+r)>>1;
build((i<<1),l,mid);
build((i<<1)|1,mid+1,r);
pushup(i);
}
void update(int i,int l,int r)
{
if(segtree[i].flag) return ;
if(segtree[i].l==segtree[i].r)
{
segtree[i].sum=sqrt(segtree[i].sum);
if(segtree[i].sum==0||segtree[i].sum==1) segtree[i].flag=true;
return ;
}
int mid=(segtree[i].l+segtree[i].r)>>1;
if(l>=(mid+1))
update((i<<1)|1,l,r);
else
if(r<=mid)
update(i<<1,l,r);
else
{
update((i<<1)|1,mid+1,r);
update(i<<1,l,mid);
}
if(segtree[i<<1].flag==true&&segtree[(i<<1)|1].flag==true)
segtree[i].flag=true;
pushup(i);
}
long long query(int i,int l,int r)
{
long long ans=0;
if(segtree[i].l>=l&&segtree[i].r<=r)
{
return segtree[i].sum;
}
int mid=(segtree[i].l+segtree[i].r)>>1;
if(l>=(mid+1))
ans+=query((i<<1)|1,l,r);
else
if(r<=mid)
ans+=query(i<<1,l,r);
else
{
ans+=query(i<<1,l,mid);
ans+=query((i<<1)|1,mid+1,r);
}
return ans;
}
int main()
{
int mycase=0;
while(scanf("%d",&n)!=EOF)
{
mycase++;
printf("Case #%d:
",mycase);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
scanf("%d",&m);
while(m--)
{
int t,x,y;
scanf("%d%d%d",&t,&x,&y);
if (x > y) { swap(x, y); }
//cout<<"opretion "<<t<<" "<<x<<" "<<y<<endl;
if(!t)
{
update(1,x,y);
//cout<<"/区间1到1的值:"<<segtree[4].sum<<" "<<"/区间2到2的值:"<<segtree[5].sum<<" "<<"/区间3到3的值:"<<segtree[6].sum<<" "<<"/区间4到4的值:"<<segtree[7].sum<<endl;
}
else
printf("%lld
",query(1,x,y));
}
printf("
");
}
return 0;
}