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

问题描述

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: [email protected]
    > 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;
}
时间: 2024-10-04 00:18:11

NOJ1560---Let Slimes Grow Up(线段树)的相关文章

ACM学习历程——POJ3321 Apple Tree(搜索,线段树)

      Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by bran

#5 DIV2 A POJ 3321 Apple Tree 摘苹果 构建线段树

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25232   Accepted: 7503 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

POJ 3321 Apple Tree 【树形结构转变为线性结构+线段树OR树状数组】

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21587   Accepted: 6551 POJ 3321链接: Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so

[hdu 5032]2014北京网络赛Always Cook Mushroom 离散化+离线线段树/树状数组

Always Cook Mushroom Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 196    Accepted Submission(s): 54 Problem Description Matt has a company, Always Cook Mushroom (ACM), which produces high-q

线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序 给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点. 作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致. 然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]. 最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

bzoj1798: [Ahoi2009]Seq 维护序列seq 线段树

题目传送门 这道题就是线段树 先传乘法标记再传加法 #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int M=400010; LL read(){ LL ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击