@lunar
2016-04-08T21:17:54.000000Z
字数 3314
阅读 1219
HiHo一下的合集参见这里,不断更新
HiHo
在这个游戏里,会不断的发生如下两种事件:一种是房屋自发的涨价或者降价,而另一种是政府有关部门针对房价的硬性调控。房价的变化自然影响到小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
这个题目一看,又是用线段树,但是这里比较复杂的是有两种不同的操作,其中难点就在于搞清这两种操作的关系,我们还是用懒惰标记来维护线段树,但是由于操作有两种,所以要分为两个懒惰标记。一个是sflag一个是cflag。s表示设置价格,c表示浮动价格。
每次更新到某个节点时会出现以下情况:
最后每次更新完之后输出根节点的值就可以了。
#include<iostream>
using namespace std;
#define MAX 100005
#define lchild p<<1
#define rchild p<<1|1
int tree[3*MAX];
int cflag[3*MAX];
int sflag[3*MAX];
int price[MAX];
void buildTree(int l, int r, int p){
if(l==r){
tree[p] = price[l];
cflag[p] = 0;
sflag[p] = -1;
return ;
}
int m = (l+r)>>1;
buildTree(l,m,lchild);
buildTree(m+1,r,rchild);
tree[p] = tree[lchild] + tree[rchild];
cflag[p] = 0;
sflag[p] = -1;
}
void release(int l, int r,int p){
if(l!=r){
int m = (l+r)>>1;
if(sflag[p] != -1){
sflag[lchild] = sflag[p];
sflag[rchild] = sflag[p];
cflag[lchild] = 0;
cflag[rchild] = 0;
tree[lchild] = (m-l+1) * sflag[p];
tree[rchild] = (r-m) * sflag[p];
sflag[p] = -1;
}
if(cflag[p] != 0){
tree[lchild] += (m-l+1) * cflag[p];
tree[rchild] += (r-m) * cflag[p];
cflag[lchild] += cflag[p];
cflag[rchild] += cflag[p];
cflag[p] = 0;
}
}
}
void setupdate(int l, int r, int v, int L, int R, int p){
if(L==R){
tree[p] = v;
cflag[p] = 0;
sflag[p] = -1;
return;
}
if(sflag[p]!=-1||cflag[p]!=0) release(L,R,p);
if(l<=L&&r>=R){
tree[p] = (R-L+1) * v;
sflag[p] = v;
cflag[p] = 0;
return;
}
int M = (L+R)>>1;
if(l<=M) setupdate(l,r,v,L,M,lchild);
if(r>M) setupdate(l,r,v,M+1,R,rchild);
tree[p] = tree[lchild] + tree[rchild];
return ;
}
void addupdate(int l, int r, int v, int L, int R, int p){
if(L==R){
tree[p] += v;
cflag[p] = 0;
sflag[p] = -1;
return;
}
if(sflag[p]!=-1||cflag[p]!=0) release(L,R,p);
if(l<=L&&r>=R){
tree[p] += (R-L+1) * v;
sflag[p] = -1;
cflag[p] += v;
return;
}
int M = (L+R)>>1;
if(l<=M) addupdate(l,r,v,L,M,lchild);
if(r>M) addupdate(l,r,v,M+1,R,rchild);
tree[p] = tree[lchild] + tree[rchild];
return ;
}
int main(){
int n,m;
cin >> n >> m;
for(int i=0;i<=n;i++) cin >> price[i];
buildTree(0,n,1);
while(m--){
int a,b,c,d;
cin >> a >> b >> c >> d;
if(a)setupdate(b,c,d,0,n,1);
else addupdate(b,c,d,0,n,1);
cout << tree[1]<<endl;
// cout << endl;
// show(0,n,1);
// cout <<endl;
}
return 0;
}