一看就是成段更新需要lazy,使劲一个一个更新肯定是不行的。。。
思路是判断要不要更新每个区间,有的时候是不需要更新的,然后标记成lazy以后不更新就好了。。
之前一直不是很理解lazy还是,现在也是略懂状态。。总之继续努力吧。。蒟蒻。。
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int MAX=1000000;
struct pr {
long long sum;
int lazy;
int left,right; //对应区间,注意区别rr,ll
}tr[MAX+10];
int n;
inline int ll(int k) {return 2*k;} //左边的下标
inline int rr(int k) {return 2*k+1;} //右边的下标
inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}
void pushdown(int k) {
if (tr[k].lazy==0) {
int l=tr[k].left,r=tr[k].right;
if(tr[k].sum==(r-l+1)){
tr[k].lazy=1;
}
}
}
void build(int k,int s,int t) {
tr[k].left=s;tr[k].right=t;
if(s==t) {scanf("%lld",&tr[k].sum);return;} //开始最下面是多少
build(ll(k),s,mid(s,t));
build(rr(k),mid(s,t)+1,t);
tr[k].sum=tr[ll(k)].sum+tr[rr(k)].sum;
}
void modify(int k,int s,int t) {
int l=tr[k].left,r=tr[k].right;
if(tr[k].lazy&&s==l&&r==t){
return ;
}
if(l==r){
tr[k].sum=(long long)(floor(sqrt(tr[k].sum)+1e-5));
return ;
}
int mi=mid(l,r);
if(t<=mi) modify(ll(k),s,t);
else if(s>mi) modify(rr(k),s,t);
else {
modify(ll(k),s,mi);
modify(rr(k),mi+1,t);
}
tr[k].sum=tr[ll(k)].sum+tr[rr(k)].sum;
pushdown(k);
}
long long query(int k,int s,int t) {
int l=tr[k].left,r=tr[k].right;
if(l==s&&r==t) return tr[k].sum;
int mi=mid(l,r);
long long res=0;
if (t<=mi) res+=query(ll(k),s,t);
else if(s>mi) res+=query(rr(k),s,t);
else res+=(query(ll(k),s,mi)+query(rr(k),mi+1,t));
return res;
}
int main()
{
int ii=1;
while(cin>>n){
memset(tr,0,sizeof(tr));
build(1,1,n);
cout<<"Case #"<<ii++<<":"<<endl;
int m;
cin>>m;
int a,b,c;
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
if(b>c)
swap(b,c);
if(a==0){
modify(1,b,c);
}
else
cout<<query(1,b,c)<<endl;
}
cout<<endl;
}
return 0;
}