首页 > 代码库 > ZOJ 2706 Thermal Death of the Universe(线段树区间更新)

ZOJ 2706 Thermal Death of the Universe(线段树区间更新)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1706


Johnie has recently learned about the thermal death concept. Given that the Global Entropy always increases, it will end in the thermal death of the Universe. The idea has impressed him extremely. Johnie does not want the universe to die this way.

So he decided to emulate the process to check how soon the thermal death can occur. He has created the mathematical model of the process in the following way. The universe is represented as an array of n integer numbers. The life of the universe is represented as the sequence of the following entropy operations: take elements fromith to jth and replace them with their average value. Since their average is not necessarily integer, it is rounded.

To keep balance, rounding is performed either up, or down depending on the current sum of all elements of the array. If their sum is less or equal to the sum of the original array, the rounding is performed up, in the other case --- down.

Given the initial array and the sequence of the entropy operations, find the contents of the resulting array.

Input

There are mutiple cases in the input file.

The first line of each case contains n and m --- the size of the array and the number of operations respectively (1 <= m, n <= 30,000 ). The second line contains n integer numbers --- the initial contents of the array, they do not exceed 109 by their absolute value. The following m lines contain two integer numbers each and describe entropy operations.

There is an empty line after each case.

Output

Output n integer numbers --- the contents of the array after all operations.

There should be am empty line after each case.

Sample Input

6 4
1 2 3 4 5 6
1 2
2 5
5 6
4 6

Sample Output

2 3 3 5 5 5


Source: Andrew Stankevich‘s Contest #10


题意:
给n个数,m个操作,每次把区间[l,r]的数用它们都的它们的平均值替代,
如果它们的平均值不是整数,并且当前n个数的和小于最初n个数的和就向上取整,不然就向下取整;

代码如下:

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define LL long long
const int maxn = 111111;
LL add[maxn<<2];//用来标记每个节点,为0则表示没有标记,否则为标记;
LL sum[maxn<<2];//求和
LL SUM = 0;
LL ans = 0;
void PushUp(LL rt) //把当前结点的信息更新到父结点
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(LL rt,LL len)//把当前结点的信息更新给儿子结点,len为分区间长度
{
    if (add[rt]) //已经标记过,该区间被改变过
    {
        add[rt<<1] = add[rt];
        add[rt<<1|1] = add[rt];
        sum[rt<<1] = add[rt] * (len - (len >> 1));//更新左儿子的和
        sum[rt<<1|1] = add[rt] * (len >> 1);//更新右儿子的和
        add[rt] = 0;//将标记向儿子节点移动后,父节点的延迟标记去掉
        //传递后,当前节点标记域清空
    }
}
void build(LL l,LL r,LL rt)
{
    add[rt] = 0;//初始化为所有结点未被标记
    if (l == r)
    {
        scanf("%lld",&sum[rt]);
        SUM += sum[rt];
        return ;
    }
    LL mid = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void update(LL L,LL R,LL c,LL l,LL r,LL rt)
{
    if (L <= l && r <= R)
    {
        add[rt] = c;
        sum[rt] = (LL)c * (r - l + 1);
        return ;
    }
    PushDown(rt , r - l + 1);//----延迟标志域向下传递
    LL mid = (l + r) >> 1;
    if (L <= mid)
        update(L , R , c , lson);
    if (mid < R)
        update(L , R , c , rson);
    PushUp(rt);//向上传递更新和
}
LL query(LL L,LL R,LL l,LL r,LL rt)
{
    if(L <= l && r <= R)
    {
        return sum[rt];
    }//要取rt子节点的值时,也要先把rt的延迟标记向下移动
    PushDown(rt , r - l + 1);
    LL mid = (l + r) >> 1;
    LL ret = 0;
    if (L <= mid)
        ret += query(L , R , lson);
    if (mid < R)
        ret += query(L , R , rson);
    return ret;
}
int main()
{
    LL N , Q;
    while(~scanf("%lld%lld",&N,&Q))//N为节点数
    {
        SUM = 0;
        build(1 , N , 1);
        while(Q--)
        {
            char op[2];
            LL a , b , c;
            scanf("%lld%lld",&a,&b);
            double tt = query(a , b , 1 , N , 1);
            tt /= (b-a+1)*1.0;
            if(query(1 , N , 1 , N , 1) <= SUM)
            {
                ans = (LL)ceil(tt);
            }
            else
            {
                ans = (LL)floor(tt);
            }
            update(a , b , ans , 1 , N , 1);
        }
        for(int i = 1; i < N; i++)
        {
            printf("%lld ",query(i, i, 1, N , 1));
        }
        printf("%lld\n\n",query(N, N, 1, N , 1));
    }
    return 0;
}







ZOJ 2706 Thermal Death of the Universe(线段树区间更新)