做法:求平均值是,上取整下取整要考虑正负数啊,然后更新区间时要不要直接除以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;
}