1 // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence
2 // 题意:三种操作,1增加值,2开根,3求和
3 // 思路:这题与HDU 4027 和HDU 5634 差不多
4 // 注意开根号的话,遇到极差等于1的,开根号以后有可能还是差1.如
5 // 2 3 2 3。。。
6 // 8 9 8 9。。。
7 // 2 3 2 3。。。
8 // 8 9 8 9。。。
9 // 剩下就是遇到区间相等的话,就直接开根号不往下传
10
11
12 #include <bits/stdc++.h>
13 using namespace std;
14 #define LL long long
15 const int inf = 0x3f3f3f3f;
16 const int MOD =998244353;
17 const int N =1e5+10;
18 #define clc(a,b) memset(a,b,sizeof(a))
19 const double eps = 1e-7;
20 void fre(){freopen("in.txt","r",stdin);}
21 void freout() {freopen("out.txt","w",stdout);}
22 inline int read() {int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
23 int n,q;
24 int a[N];
25 struct node{
26 int l,r,len;
27 LL sum,lazy;
28 LL mx,mn;
29 }t[N<<2];
30
31 void pushup(int rt){
32 t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;
33 t[rt].mx=max(t[rt<<1].mx,t[rt<<1|1].mx);
34 t[rt].mn=min(t[rt<<1|1].mn,t[rt<<1].mn);
35 }
36 void pushdown(int rt){
37 if(t[rt].lazy){
38 t[rt<<1].lazy+=t[rt].lazy;
39 t[rt<<1].mx+=t[rt].lazy;
40 t[rt<<1].mn+=t[rt].lazy;
41 t[rt<<1].sum+=t[rt<<1].len*t[rt].lazy;
42 t[rt<<1|1].lazy+=t[rt].lazy;
43 t[rt<<1|1].mx+=t[rt].lazy;
44 t[rt<<1|1].mn+=t[rt].lazy;
45 t[rt<<1|1].sum+=t[rt<<1|1].len*t[rt].lazy;
46 t[rt].lazy=0;
47 }
48 }
49 void build(int rt,int l,int r){
50 t[rt].l=l;
51 t[rt].r=r;
52 t[rt].lazy=0;
53 t[rt].mx=0;
54 t[rt].mn=inf;
55 t[rt].len=r-l+1;
56 if(l==r){
57 t[rt].sum=a[l],t[rt].mx=t[rt].mn=a[l];
58 return;
59 }
60 int mid=(l+r)>>1;
61 build(rt<<1,l,mid);
62 build(rt<<1|1,mid+1,r);
63 pushup(rt);
64 }
65
66 void update1(int rt,int l,int r,int z){
67 if(t[rt].l>=l&&t[rt].r<=r){
68 t[rt].sum+=(LL)t[rt].len*z;
69 t[rt].lazy+=z;
70 t[rt].mn+=z;
71 t[rt].mx+=z;
72 return;
73 }
74 pushdown(rt);
75 int mid=(t[rt].l+t[rt].r)>>1;
76 if(r<=mid) update1(rt<<1,l,r,z);
77 else if(l>mid) update1(rt<<1|1,l,r,z);
78 else {
79 update1(rt<<1,l,mid,z);
80 update1(rt<<1|1,mid+1,r,z);
81 }
82 pushup(rt);
83 }
84
85 void update2(int rt,int l,int r){
86 if(t[rt].l>=l&&t[rt].r<=r){
87 if(t[rt].mx==t[rt].mn){
88 LL tem=(LL)sqrt(t[rt].mx);
89 t[rt].sum=(LL)tem*t[rt].len;
90 t[rt].lazy-=(t[rt].mx-tem);
91 t[rt].mx=t[rt].mn=tem;
92 return;
93 }
94 else if(t[rt].mx==t[rt].mn+1){
95 LL tem1=(LL)sqrt(t[rt].mx);
96 LL tem2=(LL)sqrt(t[rt].mn);
97 if(tem1==tem2+1){
98 t[rt].sum-=(LL)(t[rt].mx-tem1)*t[rt].len;
99 t[rt].lazy-=(t[rt].mx-tem1);
100 t[rt].mx=tem1;
101 t[rt].mn=tem2;
102 return;
103 }
104 }
105 }
106 pushdown(rt);
107 int mid=(t[rt].l+t[rt].r)>>1;
108 if(r<=mid) update2(rt<<1,l,r);
109 else if(l>mid) update2(rt<<1|1,l,r);
110 else {
111 update2(rt<<1,l,mid);
112 update2(rt<<1|1,mid+1,r);
113 }
114 pushup(rt);
115 }
116
117 LL query(int rt,int l,int r){
118 if(t[rt].l>=l&&t[rt].r<=r){
119 return t[rt].sum;
120 }
121 pushdown(rt);
122 int mid=(t[rt].l+t[rt].r)>>1;
123 if(r<=mid) return query(rt<<1,l,r);
124 else if(l>mid) return query(rt<<1|1,l,r);
125 else {
126 return query(rt<<1,l,mid)+query(rt<<1|1,mid+1,r);
127 }
128 }
129 int main(){
130 int T;
131 scanf("%d",&T);
132 while(T--){
133 scanf("%d%d",&n,&q);
134 for(int i=1;i<=n;i++) {
135 scanf("%d",&a[i]);
136 }
137 build(1,1,n);
138 while(q--){
139 int op,x,y,z;
140 scanf("%d%d%d",&op,&x,&y);
141 if(op==1){
142 scanf("%d",&z);
143 update1(1,x,y,z);
144 }
145 else if(op==2){
146 update2(1,x,y);
147 }
148 else {
149 LL ans=query(1,x,y);
150 printf("%I64d
",ans);
151 }
152 }
153 }
154 return 0;
155 }