<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; }