传说中的大妈套题啊。
讲区间值转换为平均值。取平均值需要和之前区间总和和最初总和的状态有关,决定平均值是向上取整还是想下。
其中计算上一次结束后的总和很简单,用之前的减去替换区间的值,再加上替换后的值即可,不用再用线段树求所有区间的总和,那样比较费时间。
注意得用long long,平均值可以不用。
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")
using namespace std;
const int MAX = 30010;
struct Tnode{
int l,r,cover,val;
};
Tnode node[MAX<<2];
int a[MAX];
void init()
{
memset(node,0,sizeof(node));
}
void Updata_cover(int t)
{
if( node[R(t)].cover && node[L(t)].cover && node[R(t)].val == node[L(t)].val && node[L(t)].val != -1 )
{
node[t].val = node[L(t)].val;
node[t].cover = 1;
}
else
node[t].cover = 0;
}
void Build(int t,int l,int r)
{
node[t].l = l; node[t].r = r;
node[t].val = -1;
if( node[t].l == node[t].r - 1 )
{
node[t].val = a[l];
node[t].cover = 1;
return ;
}
int mid = MID(l,r);
Build(L(t),l,mid);
Build(R(t),mid,r);
Updata_cover(t);
}
void Pushdown(int t)
{
if( node[t].l == node[t].r - 1 ) return ;
if( node[t].cover )
{
node[R(t)].cover = node[L(t)].cover = 1;
node[R(t)].val = node[L(t)].val = node[t].val;
}
}
void Updata(int t,int l,int r,int val)
{
Pushdown(t);
if( node[t].l >= l && node[t].r <= r )
{
node[t].cover = 1;
node[t].val = val;
return ;
}
if( node[t].l == node[t].r - 1 ) return ;
int mid = MID(node[t].l,node[t].r);
if( l <= mid )
Updata(L(t),l,r,val);
if( r > mid )
Updata(R(t),l,r,val);
Updata_cover(t);
}
long long Query(int t,int l,int r)
{
Pushdown(t);
if( node[t].cover )
return (r - l)*1ll*node[t].val;
if( node[t].l == node[t].r - 1 ) return 0;
int mid = MID(node[t].l,node[t].r);
int ans = 0;
if( l >= mid )
return Query(R(t),l,r);
else
if( r < mid )
return Query(L(t),l,r);
else
return Query(L(t),l,mid) + Query(R(t),mid,r);
}
void Query_last(int t)
{
if( node[t].cover )
{
for(int i=node[t].l; i<node[t].r; i++)
a[i] = node[t].val;
return ;
}
if( node[t].l == node[t].r - 1 ) return ;
Query_last(L(t));
Query_last(R(t));
}
long long Asum(long long cur,long long s,long long sum,int y,int x)
{
if( cur <= s )
{
if( sum >= 0 )
return (long long)ceil(sum/(y-x+1.0));
return sum/(y-x+1);
}
if( sum >= 0 )
return sum/(y-x+1);
return -(long long)ceil(-sum/(y-x+1.0));
}
int main()
{
int n,m,x,y;
long long cur,s;
while( ~scanf("%d%d",&n,&m) )
{
init();
s = 0ll;
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
s += a[i];
}
Build(1,0,n);
cur = s;
while( m-- )
{
scanf("%d%d",&x,&y);
long long sum = Query(1,x-1,y);
long long tmp = sum;
sum = Asum(cur,s,sum,y,x);
cur = cur - tmp + sum*(y-x+1);
Updata(1,x-1,y,sum);
}
Query_last(1);
for(int i=0; i<n-1; i++)
printf("%d ",a[i]);
printf("%d\n\n",a[n-1]);
}
return 0;
}