<p>题目链接:<a target=_blank href="http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2706">点击打开链接</a></p><p>
</p><p>
</p><p>题意:对一段数字做一种操作:把l~r范围里的所有数变为他们的平均数。如果这个平均数不是整数,那么如果当前序列所有数的和<=初始序列的和就向上取整,反之向下取整。</p><p>
</p><p>成段更新每个结点总值,打lazy标记。</p><p>注意整数除法中正数是向下取整,负数是向上取整,要分情况讨论。</p><p>
</p><p>代码:</p>
#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
#define MAX 30010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
ll sum[MAX<<2];
ll col[MAX<<2];
ll a[MAX];
void pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int len){
if(col[rt]){
col[rt<<1]=col[rt<<1|1]=col[rt];
sum[rt<<1]=col[rt]*(len-(len>>1));
sum[rt<<1|1]=col[rt]*(len>>1);
col[rt]=0;
}
}
void build(int l,int r,int rt){
col[rt]=0;
if(l==r){
scanf("%lld",&sum[rt]);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,ll v,int l,int r,int rt){
if(L<=l&&R>=r){
sum[rt]=v*(r-l+1);
col[rt]=v;
return ;
}
pushdown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m) update(L,R,v,lson);
if(R>m) update(L,R,v,rson);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r) return sum[rt];
pushdown(rt,r-l+1);
ll res=0;
int m=(l+r)>>1;
if(L<=m) res+=query(L,R,lson);
if(R>m) res+=query(L,R,rson);
return res;
}
void solve(int l,int r,int rt){
if(l==r){
a[l]=sum[rt];
return ;
}
pushdown(rt,r-l+1);
int m=(l+r)>>1;
solve(lson);
solve(rson);
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
build(1,n,1);
ll org=sum[1];
for(int i=1;i<=m;i++){
int s,t;
scanf("%d%d",&s,&t);
ll tmp=query(s,t,1,n,1);
ll k=tmp/(t-s+1);
if(tmp%(t-s+1)!=0){
if(sum[1]<=org){
if(tmp>0) k++;
}
if(sum[1]>org){
if(tmp<0) k--;
}
}
update(s,t,k,1,n,1);
}
solve(1,n,1);
for(int i=1;i<n;i++){
printf("%d ",a[i]);
}
printf("%d\n\n",a[n]);
}
return 0;
}