码迷,mamicode.com
首页 > 其他好文 > 详细

NOJ1560---Let Slimes Grow Up(线段树)

时间:2015-04-17 11:45:39      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:线段树

问题描述
You know 8Mao has his own Slime Team. But he soon found that let the Slimes stand in a line and make them from low to high is a such stupid thing since the Slimes are so f[bi][bi]king stupid!
As a result, 8Mao decided to give up.
But 8Mao still want his Slime Team be beautiful. So he got up another idea, let his Slimes grow up. He got some medicine that can make the Slimes in the line get higher. But only can let continuous Slimes.
8Mao thought that the variance of the heights of Slimes in the line is smaller, the Slime Team is more beautiful.
You have to help 8Mao to calculate out the variance of Slimes in a continuous sequence.
输入
This problem contains several cases, ends with EOF.
The first line of each case contains 2 integers N and M which N indicates the number of Slimes and the number of operations.
Next line contains the heights of each Slimes ordered from 0 ~ N - 1. (0 < height <= 100, 000)
Then M lines followed. Each line indicates one operation.
If the operator is “1”, then follows 3 integers A, B and C which indicate the start number of the Slimes and the end number of the Slimes and the heights the Slimes between A and B will increase.
If the operator is “2”, then follows 2 integers A and B, you have to calculate out the variance of heights between Slime A and Slime B.
输出
For each operator “2”, you should output the variance. (The answer should be formatted to integer)
样例输入

5 3
1 4 3 2 5
2 0 4
1 1 2 2
2 0 4

样例输出

2
3

提示

来源

cjl

操作

要求区间内的方差,把方差公式转换以后,变成维护区间和和区间平方和,然后线段树乱搞下就行,
这题是去年校赛的,可惜那时太弱根本不会

/*************************************************************************
    > File Name: NOJ1560.cpp
    > Author: ALex
    > Mail: zchao1995@gmail.com 
    > Created Time: 2015年04月16日 星期四 20时22分13秒
 ************************************************************************/

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>

using namespace std;

const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

static const int N = 100100;
struct node
{
    int l, r;
    LL sum;
    LL sumsum;
    LL add;
}tree[N << 2];

void build(int p, int l, int r)
{
    tree[p].l = l;
    tree[p].r = r;
    tree[p].add = 0;
    if (l == r)
    {
        scanf("%lld", &tree[p].sum);
        tree[p].sumsum = tree[p].sum * tree[p].sum;
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
    tree[p].sumsum = tree[p << 1].sumsum + tree[p << 1 | 1].sumsum;
}

void pushdown(int p)
{
    if (tree[p].add)
    {
        tree[p << 1].add += tree[p].add;
        tree[p << 1 | 1].add += tree[p].add;
        int m = tree[p << 1].r - tree[p << 1].l + 1; //左子树长度
        LL use = tree[p].add;
        LL sum1 = tree[p << 1].sum;
        tree[p << 1].sum += use * m;
        tree[p << 1].sumsum += m * use * use + 2 * use * sum1;
        LL sum2 = tree[p << 1 | 1].sum;
        m = tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1;
        tree[p << 1 | 1].sum += use * m;
        tree[p << 1 | 1].sumsum += m * use * use + 2 * use * sum2;
        tree[p].add = 0;
    }
}

void update(int p, int l, int r, LL val)
{
    if (tree[p].l == l && r == tree[p].r)
    {
        tree[p].add += val;
        int m = r - l + 1;
        LL sum = tree[p].sum;
        tree[p].sum += m * val;
        tree[p].sumsum += val * val * m + 2 * val * sum;
        return;
    }
    pushdown(p);
    int mid = (tree[p].l + tree[p].r) >> 1;
    if (r <= mid)
    {
        update(p << 1, l, r, val);
    }
    else if (l > mid)
    {
        update(p << 1 | 1, l, r, val);
    }
    else
    {
        update(p << 1, l, mid, val);
        update(p << 1 | 1, mid + 1, r, val);
    }
    tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
    tree[p].sumsum = tree[p << 1].sumsum + tree[p << 1 | 1].sumsum;
}

LL sumsum, sum;

void query(int p, int l, int r)
{
    if (l == tree[p].l && r == tree[p].r)
    {
        sum += tree[p].sum;
        sumsum += tree[p].sumsum;
        return;
    }
    int mid = (tree[p].l + tree[p].r) >> 1;
    pushdown(p);
    if (r <= mid)
    {
        query(p << 1, l, r);
    }
    else if (l > mid)
    {
        query(p << 1 | 1, l, r);
    }
    else
    {
        query(p << 1, l, mid);
        query(p << 1 | 1, mid + 1, r);
    }
}

int main()
{
    int n, m;
    while (~scanf("%d%d", &n, &m))
    {
        int op, x, y;
        LL val;
        build(1, 1, n);
        while (m--)
        {
            scanf("%d", &op);
            if (op == 1)
            {
                scanf("%d%d%lld", &x, &y, &val);
                ++x;
                ++y;
                update(1, x, y, val);
            }
            else
            {
                scanf("%d%d", &x, &y);
                ++x;
                ++y;
                sum = 0;
                sumsum = 0;
                query(1, x, y);
                double _x = sum * 1.0 / (y - x + 1);
                double ans = ((y - x + 1) * _x * _x - 2 * _x * sum + sumsum) * 1.0;
                ans /= (y - x + 1);
                cout << (LL)ans << endl;
            }
        }
    }
    return 0;
}

NOJ1560---Let Slimes Grow Up(线段树)

标签:线段树

原文地址:http://blog.csdn.net/guard_mine/article/details/45080947

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!