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;
}