J题题解。观察f(x)可以发现对于每个x,经过不多次操作后就会变成0。因此可以用线段树维护区间是否已经修改完毕,如果没有修改完毕就暴力修改,否则直接return。对于操作2直接维护区间和回答询问即可。
```#include<bits/stdc++.h>
#include<queue>
#include<string.h>
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#define int long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define nl tree[n].l
#define nr tree[n].r
#define gcd __gcd
using namespace std;
//#pragma GCC optimize(2)
const int maxn=1e6+50;
const int inf=1e18;
const int mod=1e9+7;
const int INF=2e18;
const double eps=1e-8;
const double delta=0.98;
int f(int x)
{
x=abs(x*x*x-3*x)/(3*x*x+1);
x*=2;
return x;
}
int a[maxn];
struct node{
int l,r,sum,f;
}tree[maxn<<2];
void push_pug(int n)
{
tree[n].sum=tree[n<<1].sum+tree[n<<1|1].sum;
tree[n].f=tree[n<<1].f&tree[n<<1|1].f;
}
void build(int n,int l,int r)
{
nl=l,nr=r;
if(l==r)
{
tree[n].sum=a[l];
tree[n].f=0;
return;
}
int mid=l+r>>1;
build(n<<1,l,mid);
build(n<<1|1,mid+1,r);
push_pug(n);
}
void add(int n,int l,int r)
{
if(tree[n].f==1) return;
if(nl==nr)
{
int ok=f(tree[n].sum);
if(ok==tree[n].sum) tree[n].f=1;
tree[n].sum=ok;
return;
}
int mid=nl+nr>>1;
if(l<=mid&&tree[n<<1].f==0) add(n<<1,l,r);
if(r>mid&&tree[n<<1|1].f==0) add(n<<1|1,l,r);
push_pug(n);
}
int query(int n,int l,int r)
{
if(nl>=l&&nr<=r) return tree[n].sum;
int mid=nl+nr>>1;
int res=0;
if(l<=mid) res+=query(n<<1,l,r);
if(r>mid) res+=query(n<<1|1,l,r);
return res;
}
void solve()
{
int n,q;
cin>>n>>q;
rep(i,1,n) cin>>a[i];
build(1,1,n);
while(q--)
{
int op,l,r;
cin>>op>>l>>r;
if(op==1) add(1,l,r);
else cout<<query(1,l,r)<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int __=1;
//cin>>__;
//euler(2e5);
while(__--)
{
solve();
}
return 0;
}