rt, 思路是先平方,再还原,马蜂优良,题解区没有的思路,但很好理解QWQ
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 5;
int pos[N], add[N], a[N], sum[N], st[N], ed[N];
bool flag[N];
void update0(int x, int y, int c)
{
int p = pos[x], q = pos[y];
if(p == q)
{
for(int i = x;i <= y;i ++ ) a[i] += c;
sum[p] += c * (y - x) + 1;
}
else
{
for(int i = p + 1;i < q;i ++ ) add[i] += c;
for(int i = x;i <= ed[p];i ++ ) a[i] += c;
sum[p] += (ed[p] - x) * c;
for(int i = st[q];i <= y;i ++ ) a[i] += c;
sum[q] += (y - st[q]) * c;
}
}
void work(int x)
{
if(flag[x]) return ;
flag[x] = true;
sum[x] = 0;
for(int i = st[x];i <= ed[x];i ++ ){
a[i] = pow(a[i], 2), sum[x] += a[i];
if(a[i] > 1) flag[x] = false;
}
}
void update(int l, int r, int k)
{
int p = pos[l], p1 = pos[r];
if(p == p1)
{
for(int i = l;i <= r;i ++ ) {
sum[p] -= a[i];
a[i] = pow(a[i], 2);
sum[p] += a[i];
}
}
else {
for(int i = p + 1;i < p1;i ++ ) work(i);
for(int i = l;i <= ed[p];i ++ ) sum[p] -= a[i], a[i] = pow(a[i], 2), sum[p] += a[i];
for(int i = st[p1];i <= r;i ++ ) sum[p1] -= a[i], a[i] = pow(a[i], 2), sum[p1] += a[i];
}
}
void work1(int x)
{
if(flag[x]) return ;
flag[x] = true;
sum[x] = 0;
for(int i = st[x];i <= ed[x];i ++ ){
a[i] = sqrt(a[i]), sum[x] += a[i];
if(a[i] > 1) flag[x] = false;
}
}
void update1(int l, int r, int k)
{
int p = pos[l], p1 = pos[r];
if(p == p1)
{
for(int i = l;i <= r;i ++ ) {
sum[p] -= a[i];
a[i] = sqrt(a[i]);
sum[p] += a[i];
}
}
else {
for(int i = p + 1;i < p1;i ++ ) work1(i);
for(int i = l;i <= ed[p];i ++ ) sum[p] -= a[i], a[i] = sqrt(a[i]), sum[p] += a[i];
for(int i = st[p1];i <= r;i ++ ) sum[p1] -= a[i], a[i] = sqrt(a[i]), sum[p1] += a[i];
}
}
int query(int l, int r)
{
int p = pos[l], p1 = pos[r];
int ans = 0;
if(p == p1)
{
for(int i = l;i <= r;i ++ ) ans += a[i];
ans += (r - l + 1) * add[p];
}
else {
for(int i = p + 1;i < p1;i ++ ) ans += sum[i] + add[i] * (ed[i] - st[i] + 1);
for(int i = l;i <= ed[p];i ++ ) ans += a[i];
ans += add[p] * (ed[p] - l + 1);
for(int i = st[p1];i <= r;i ++ ) ans += a[i];
ans += add[p1] * (r - st[p1] + 1);
}
return ans;
}
signed main()
{
int n, m;
cin >> n >> m;
for(int i = 1;i <= n;i ++ ) cin >> a[i];
int block = sqrt(n);
int cnt = n / block;
if(n % block) cnt ++ ;
for(int i = 1;i <= cnt;i ++ ){
st[i] = (i - 1) * block + 1;
ed[i] = i * block;
}
ed[cnt] = n;
for(int i = 1;i <= n;i ++ ) pos[i] = (i - 1) / block + 1;
for(int i = 1;i <= cnt;i ++ ){
for(int j = st[i];j <= ed[i];j ++ ){
sum[i] += a[j];
}
}
while(m -- )
{
int op, x, y;
cin >> op;
if(op == 1){
int k;
cin >> x >> y >> k;
update0(x, y, k);
}
else if(op == 2){
int k;
cin >> x >> y;
printf("%.4lf\n", (double)query(x, y) / double(y - x + 1));
}
else if(op == 3)
{
cin >> x >> y;
update(x, y, 1);
double cnt = (double)query(x, y) / double(n) ;
update1(x, y, 1);
cnt -= pow(query(x, y) / n, 2);
printf("%.4lf\n", cnt);
}
// for(int i = 1;i <= n;i ++ ) cout << a[i] << ' ';
// cout << endl;
}
return 0;
}