做法:求平均值是,上取整下取整要考虑正负数啊,然后更新区间时要不要直接除以2了。
#include<cstdio> #include<cstring> #define left l,m,x<<1 #define right m+1,r,x<<1|1 #define LL long long const int LMT=30003; LL sum[LMT<<2],num[LMT<<2]; bool cov[LMT<<2],tag; void init(void) { memset(sum,0,sizeof(sum)); memset(cov,0,sizeof(cov)); memset(num,0,sizeof(num)); tag=0; } void cut(int x,int l,int r) { if(cov[x]) { int m=(l+r)>>1; cov[x<<1]=cov[x<<1|1]=cov[x]; num[x<<1]=num[x<<1|1]=num[x]; sum[x<<1]=(m-l+1)*num[x]; sum[x<<1|1]=(r-m)*num[x]; cov[x]=0; } } LL query(int L,int R,int l,int r,int x) { if(L<=l&&r<=R) return sum[x]; cut(x,l,r); int m=(l+r)>>1; LL res=0; if(L<=m)res+=query(L,R,left); if(R>m)res+=query(L,R,right); return res; } void update(LL op,int L,int R,int l,int r,int x) { if(L<=l&&r<=R) { cov[x]=1; num[x]=op; sum[x]=(r-l+1)*op; return; } cut(x,l,r); int m=(l+r)>>1; if(L<=m)update(op,L,R,left); if(R>m)update(op,L,R,right); sum[x]=sum[x<<1]+sum[x<<1|1]; } void see(int l,int r,int x) { if(l==r) { if(tag)printf(" "); else tag=1; printf("%lld",sum[x]); return ; } cut(x,l,r); int m=(l+r)>>1; see(left); see(right); } LL cal(LL x,int l,int r,bool up) { if(x>=0) { if(up)return (x+r-l)/(r-l+1); else return x/(r-l+1); } else { x=-x; if(!up)return -(x+r-l)/(r-l+1); else return -x/(r-l+1); } } int main() { int n,m,l,r; LL x,st,ori; while(~scanf("%d%d",&n,&m)) { init(); for(int i=0;i<n;i++) { scanf("%lld",&x); update(x,i,i,0,n-1,1); } ori=sum[1]; while(m--) { scanf("%d%d",&l,&r); l--;r--; st=query(l,r,0,n-1,1); if(ori>=sum[1])update(cal(st,l,r,1),l,r,0,n-1,1); else update(cal(st,l,r,0),l,r,0,n-1,1); } see(0,n-1,1); printf("\n\n"); } return 0; }