传说中的大妈套题啊。
讲区间值转换为平均值。取平均值需要和之前区间总和和最初总和的状态有关,决定平均值是向上取整还是想下。
其中计算上一次结束后的总和很简单,用之前的减去替换区间的值,再加上替换后的值即可,不用再用线段树求所有区间的总和,那样比较费时间。
注意得用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; }