题目链接:G-鸡格线_2023牛客寒假算法基础集训营1 (nowcoder.com)
主要思路:因为每次都从l到r执行k遍会超时,所以可以用set容器记录某些还需要改变的数,然后在后面更新的时候用函数找到l到r中间的某个需要更改的数然后进行更新。
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
typedef long long ll;
using namespace std;
set<ll>st;
ll a[100005];
ll sum=0;
ll change(ll x){
return round(10*sqrt(x));
}
int main(){
ll n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
if(a[i]!=change(a[i])){
st.insert(i);
}
}
st.insert(n+1);//防止全部都已经不需要更新后的死循环。
while(m--){
ll op;
cin>>op;
if(op==2) cout<<sum<<endl;
else {
ll l,r,k;
cin>>l>>r>>k;
ll tmp=l;
while(1){
ll nex=*(st.lower_bound(tmp));//找到第一个小于等于tmp的下标.
if(nex>r) break;
for(int i=0;i<k;i++){
sum-=a[nex];
sum+=change(a[nex]);
a[nex]=change(a[nex]);
if(a[nex]==change(a[nex]))break;
}
if(a[nex]==change(a[nex])){
st.erase(nex);
}
tmp=nex+1;
}
}
}
}