HihoCoder1080 更为复杂的买卖房屋姿势(线段树+多重lazy)
描述
小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<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> const int maxn=100010; using namespace std; int a[maxn],n; struct Node { int L,R,lazy1,lazy2,sum,cnt; Node() { L=R=lazy1=lazy2=sum=cnt=0; } }; struct Tree { Node node[maxn<<2]; void build(int now,int l,int r) { node[now].L=l; node[now].R=r; node[now].lazy1=node[now].lazy2=0; if(l==r) { node[now].cnt=1; return ; } int Mid=(l+r)>>1; build(now<<1,l,Mid); build(now<<1|1,Mid+1,r); node[now].cnt=node[now<<1].cnt+node[now<<1|1].cnt; } void update(int now) { node[now].sum=node[now<<1].sum+node[now<<1|1].sum; } void pushdown(int now) { if(node[now].lazy1){ node[now<<1].lazy1=node[now].lazy1; node[now<<1|1].lazy1=node[now].lazy1; node[now<<1].lazy2=0; node[now<<1|1].lazy2=0; node[now<<1].sum=node[now].lazy1*node[now<<1].cnt; node[now<<1|1].sum=node[now].lazy1*node[now<<1|1].cnt; node[now].lazy1=0; } if(node[now].lazy2) { node[now<<1].lazy2+=node[now].lazy2; node[now<<1|1].lazy2+=node[now].lazy2; node[now<<1].sum+=node[now].lazy2*node[now<<1].cnt; node[now<<1|1].sum+=node[now].lazy2*node[now<<1|1].cnt; node[now].lazy2=0; } } void insert(int now,int pos,int val) { if(node[now].L==node[now].R) { node[now].sum=val; return ; } int Mid=(node[now].L+node[now].R)>>1; if(pos<=Mid) insert(now<<1,pos,val); else insert(now<<1|1,pos,val); update(now); } void change(int now,int l,int r,int val,int opt) { if(node[now].L>=l&&node[now].R<=r) { if(opt==1){ node[now].lazy1=val; node[now].lazy2=0; node[now].sum=node[now].cnt*val; } else { node[now].lazy2+=val; node[now].sum+=node[now].cnt*val; } return ; } pushdown(now); int Mid=(node[now].L+node[now].R)>>1; if(Mid>=l) change(now<<1,l,r,val,opt); if(Mid<r) change(now<<1|1,l,r,val,opt); update(now); return ; } int query(int now,int l,int r) { if(node[now].L>=l&&node[now].R<=r) return node[now].sum; pushdown(now); int Mid=(node[now].L+node[now].R)>>1; int s=0; if(Mid>=l) s+=query(now<<1,l,r); if(Mid<r) s+=query(now<<1|1,l,r); update(now); return s; } }; Tree tree; int main() { int x,l,r,q,i,opt; scanf("%d%d",&n,&q); n++; tree.build(1,1,n); for(i=1;i<=n;i++) { scanf("%d",&a[i]); tree.insert(1,i,a[i]); } while(q--){ scanf("%d%d%d%d",&opt,&l,&r,&x); l++;r++; tree.change(1,l,r,x,opt); printf("%d\n",tree.query(1,0,n)); } return 0; }