hiho#1080 更为复杂的买卖房屋姿势 线段树+区间更新

#1080 : 更为复杂的买卖房屋姿势

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们可以化身上帝模式,买卖房产。

在这个游戏里,会不断的发生如下两种事件:一种是房屋自发的涨价或者降价,而另一种是政府有关部门针对房价的硬性调控。房价的变化自然影响到小Hi和小Ho的决策,所以他们希望能够知道任意时刻某个街道中所有房屋的房价总和是多少——但是很不幸的,游戏本身并不提供这样的计算。不过这难不倒小Hi和小Ho,他们将这个问题抽象了一下,成为了这样的问题:

小Hi和小Ho所关注的街道的长度为N米,从一端开始每隔1米就有一栋房屋,依次编号为0..N,在游戏的最开始,每栋房屋都有一个初始价格,其中编号为i的房屋的初始价格为p_i,之后共计发生了M次事件,所有的事件都是对于编号连续的一些房屋发生的,其中第i次事件如果是房屋自发的涨价或者降价,则被描述为三元组(L_i, R_i, D_i),表示编号在[L_i, R_i]范围内的房屋的价格的增量(即正数为涨价,负数为降价)为D_i;如果是政府有关部门针对房价的硬性调控,则被描述为三元组(L_i, R_i, V_i),表示编号在[L_i, R_i]范围内的房屋的价格全部变为V_i。而小Hi和小Ho希望知道的是——每次事件发生之后,这个街道中所有房屋的房价总和是多少。

提示:这是练习向的一周~

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第1行为两个整数N、M,分别表示街道的长度和总共发生的事件数。

每组测试数据的第2行为N+1个整数,其中第i个整数位p_i,表示编号为i的房屋的初始价格。

每组测试数据的第3-M+2行,按照发生的时间顺序,每行描述一个事件,如果该行描述的事件为,“房屋自发的涨价或者降价”,则该行为4个整数0, L_i, R_i, D_i,意义如前文所述;如果该行描述的事件为“政府有关部门针对房价的硬性调控”,则该行为4个整数1, L_i, R_i, V_i,意义如前文所述。

对于100%的数据,满足N<=10^5,1<=p_i, |D_i|, V_i<=10^4,0<=l_i<r_i<=n。<>

对于100%的数据,满足在任意时刻,任何房屋的价格都处于[1, 10^4]内。

输出

对于每组测试数据,输出M行,其中第i行为一个整数Ans_i,表示第i次事件发生之后,这个街道中所有房屋的房价总和。

样例输入
10 6
3195 2202 4613 3744 2892 4858 619 5079 9478 7366 8942
0 1 6 886
1 0 2 9710
1 0 10 7980
0 4 9 -7594
0 2 8 1581
0 4 4 -1010
样例输出
58304
75652
87780
42216
53283
52273

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define pi (4*atan(1.0))
const int N=1e5+10,M=1e6+10,inf=1e9+10;
ll sum[N*4],lazy[N*4],flag[N*4];
void pushdown(ll pos,ll len)
{
    ll lson=pos*2;
    ll rson=pos*2+1;
    if(flag[pos])
    {
        lazy[lson]=0;
        lazy[rson]=0;
        flag[lson]=flag[pos];
        flag[rson]=flag[pos];
        sum[lson]=(len-(len>>1))*flag[pos];
        sum[rson]=(len>>1)*flag[pos];
        flag[pos]=0;
    }
    if(lazy[pos])
    {
        lazy[lson]+=lazy[pos];
        lazy[rson]+=lazy[pos];
        sum[lson]+=(len-(len>>1))*lazy[pos];
        sum[rson]+=(len>>1)*lazy[pos];
        lazy[pos]=0;
    }
}
void buildtree(ll l,ll r,ll pos)
{
    lazy[pos]=0;
    flag[pos]=0;
    ll mid=(l+r)>>1;
    if(l==r)
    {
        scanf("%lld",&sum[pos]);
        return;
    }
    buildtree(l,mid,pos*2);
    buildtree(mid+1,r,pos*2+1);
    sum[pos]=sum[pos*2]+sum[pos*2+1];
}
ll query(ll L,ll R,ll l,ll r,ll pos)
{
    pushdown(pos,r-l+1);
    if(L<=l&&r<=R)
    return sum[pos];
    ll mid=(l+r)>>1;
    ll ans=0;
    if(L<=mid) ans+=query(L,R,l,mid,pos*2);
    if(mid<R)  ans+=query(L,R,mid+1,r,pos*2+1);
    return ans;
}
void update(ll L,ll R,ll c,ll l,ll r,ll pos,ll gg)
{
    pushdown(pos,(r-l+1));
    if(L<=l&&r<=R)
    {
        if(gg)
        flag[pos]=c,sum[pos]=(c*(r-l+1));
        else
        lazy[pos]+=c,sum[pos]+=(c*(r-l+1));
        return;
    }
    ll mid=(l+r)>>1;
    if(L<=mid)update(L,R,c,l,mid,pos*2,gg);
    if(mid<R)update(L,R,c,mid+1,r,pos*2+1,gg);
    sum[pos]=sum[pos*2]+sum[pos*2+1];
}
int main()
{
    ll x,y,z,i,t;
    while(~scanf("%lld%lld",&x,&y))
    {
        buildtree(1,x+1,1);
        for(i=0;i<y;i++)
        {
            ll hh,l,r,change;
            scanf("%lld%lld%lld%lld",&hh,&l,&r,&change);
            update(l+1,r+1,change,1,x+1,1,hh);
            printf("%lld\n",query(1,x+1,1,x+1,1));
        }
    }
    return 0;
}

代码

时间: 2024-11-05 16:05:38

hiho#1080 更为复杂的买卖房屋姿势 线段树+区间更新的相关文章

hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

#1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们可以化身上帝模式,买卖房产. 在这个游戏里,会不断的发生如下两种事件:一种是房屋自发的涨价或者降价,而另一种是政府有关部门针对房价的硬性调控.房价的变化自然影响到小Hi和小Ho的决策,所以他们希望能够知道任意时刻某个街道中所有房屋的房价总和是多少——但是很不幸的,游戏本身并不提供这样的计算.不过这难

hihocoder 1080 线段树(区间更新)

题目链接:http://hihocoder.com/problemset/problem/1080 , 两种操作的线段树(区间更新). 这道题前一段时间一直卡着我,当时也是基础不扎实做不出来,今天又想了想其实还是比较简单的,也只能怪自己太弱了. 这道题坑就坑在是有两个操作:set和add,所以lazy标记数组就需要两个,但是有一点要考虑的是一个区间上set与add的先后关系——如果对于一个区间set和add标记同时存在,那么应该如果处理:一种情况set在add之前,那么就按照正常顺序来就可以了:

Light OJ 1080 - Binary Simulation - (线段树区间更新 单点查询)

Description Given a binary number, we are about to do some operations on the number. Two types of operations can be here. 'I i j'    which means invert the bit from i to j (inclusive) 'Q i'    answer whether the ith bit is 0 or 1 The MSB (most signif

hiho1080 更为复杂的买卖房屋姿势

题目链接: hihocoder1080 题解思路: 题目中对区间修改有两个操作: 0   区间所有点增加v 1   区间所有点改为v 容易想到应该使用到两个懒惰标记  一个记录替换  一个记录增减 但这里会涉及到一个顺序问题 ,这里就需要考虑到 懒惰标记传递的策略: 如果出现替换标记 就应该把增减标记覆盖 如果同区间出现多个增减标记 则需要将标记叠加 代码: #include<iostream> #include<cstdio> #include<cstring> #d

hiho一下 第二十一周(线段树 离散化)

知识点1:离散化  对于这些区间来说,其实并不会在乎具体数值是多少,而是在他们的左右端点之间互相进行比较而已.所以你就把这N个区间的左右端点——2N个整数提出来,处理一下呗?你要注意的是,这2N个数是什么其实并不重要,你可以把这2N个数替换成为任何另外2N个数,只要他们之间的相对大小关系不发生改变就可以.” 解决方法: 那么我需要额外做的事情就是在构建线段树之前对区间进行预处理:将区间的左右端点选出来,组成一个集合,然后将这个集合依次对应到正整数集合上,并且利用这个对应将原来的区间的左右端点更换

[Codevs] 1080 线段树练习

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

codevs 1080 线段树练习--用树状数组做的

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

1080 线段树练习 (codevs)

http://codevs.cn/problem/1080/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Des

线段树练习 codevs 1080

/* codevs 1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Des