分块求调
  • 板块P1471 方差
  • 楼主vectorxyz
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/8/3 18:55
  • 上次更新2024/8/3 20:12:46
查看原帖
分块求调
1114241
vectorxyz楼主2024/8/3 18:55

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;
}
2024/8/3 18:55
加载中...