思路
我们没有办法直接对区间进行开方然后下传,所以pushdown就没必要写了。
对于每个数,开方6次之后达到势能上限,其结果必然为0或者1。那么对于整个区间,
可以记录开方次数(取区间内开方次数最少的那个值)是否达到6就可以了,
或者只要一个区间全为0或1的话,也可以直接返回。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n,m,op,l,r;
int tr[maxn<<2],cnt[maxn<<2];
void build(int node,int l,int r){
if(l==r){
cin>>tr[node];
return;
}
int mid=l+r>>1;
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
tr[node]=tr[node<<1]+tr[node<<1|1];
cnt[node]=cnt[node<<1]+cnt[node<<1|1];
}
int query(int node,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
return tr[node];
}
int mid=l+r>>1,res=0;
if(ql<=mid) res+=query(node<<1,l,mid,ql,qr);
if(qr>mid) res+=query(node<<1|1,mid+1,r,ql,qr);
return res;
}
void update(int node,int l,int r,int ql,int qr){
if(cnt[node]>5) return;
if(l==r){
tr[node]=sqrt(tr[node]);
cnt[node]++;
return;
}
int mid=l+r>>1;
if(ql<=mid) update(node<<1,l,mid,ql,qr);
if(qr>mid) update(node<<1|1,mid+1,r,ql,qr);
tr[node]=tr[node<<1]+tr[node<<1|1];
cnt[node]=min(cnt[node<<1],cnt[node<<1|1]);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
build(1,1,n);
for(int i=1;i<=m;i++){
cin>>op>>l>>r;
if(op==1){
update(1,1,n,l,r);
}else{
cout<<query(1,1,n,l,r)<<endl;
}
}
return 0;
} 
京公网安备 11010502036488号