给你一个数组A,每次可以指定一个大小为K区间L,R。
使得从L到R的每个数分别减1,2,3,4,5…k。
问至少需要多少次才能让数组的全部数变成非正数。
参考pzr佬
参考ygg佬
可以直接贪心的正向考虑,从a1开始这个数肯定要变成非正数,所以我们直接使用a1次将它改变,每次只减1所以得k次。
但是k个区间里的数都要减去对应的数,我们可以都减去1来求前缀(因为上面那个很明显是个公差为1的等差)。
我们还得消除这个前缀给之后的点带来的影响,所以得在R+1加上K来抵消影响。
要使用区间加减法可以用上线段树。
这样我们可以从1开始做每次取这个数的前缀加自己来判断是否需要减法。
如果反着想呢?
我们从n开始,取这个数能减的最大的数,以及减多少次,这样我们不就不需要在R+1抵消影响了吗,因为我们是从后往前,后面的数已经考虑过了。
#include
//#include
//priority_queue
#define PII pair<int,int>
#define int long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 600100;
int n , k ;
long long a[N] ;
struct node
{
int l , r ;
long long sum , lz ;
}tee[4*N] ;
void bd(int i , int l , int r )
{
tee[i].l = l , tee[i].r = r ;
if ( l == r )
{
tee[i].sum = 0 ;
tee[i].lz = 0 ;
return ;
}
int j = (l+r)/2 ;
bd(i*2,l,j);
bd(i*2+1,j+1,r) ;
tee[i].sum = tee[i*2].sum + tee[i*2+1].sum ;
tee[i].lz = 0 ;
}
void pd(int i )
{
if ( tee[i].lz != 0 )
{
tee[i*2].lz += tee[i].lz;
tee[i*2+1].lz += tee[i].lz;
tee[i*2].sum += tee[i].lz*(tee[i*2].r - tee[i*2].l + 1 );
tee[i*2+1].sum += tee[i].lz*(tee[i*2+1].r - tee[i*2+1].l + 1 );
tee[i].lz = 0 ;
}
}
long long sea(int i , int l , int r )
{
if (tee[i].l >= l && tee[i].r <= r )
return tee[i].sum ;
pd(i);
long long sum = 0 ;
if ( tee[i*2].r >= l )
sum += sea(i*2,l,r) ;
if ( tee[i*2+1].l <= r )
sum += sea(i*2+1,l,r) ;
return sum ;
}
void add(int i , int l , int r , int p )
{
if (tee[i].l >= l && tee[i].r <= r )
{
tee[i].sum += p*(tee[i].r-tee[i].l+1) ;
tee[i].lz += p ;
return ;
}
pd(i);
if ( tee[i*2].r >= l )
add(i*2,l,r,p) ;
if ( tee[i*2+1].l <= r )
add(i*2+1,l,r,p) ;
tee[i].sum = tee[i*2].sum + tee[i*2+1].sum ;
}
void solve()
{
cin >> n >> k ;
for (int i = 1 ; i <= n ; i++ )
cin >> a[i] ;
bd(1,1,n) ;
long long ans = 0 ;
for (int i = n ; i >= 1 ; i-- )
{
long long num = a[i] + sea(1,1,i) ;
//cout << sea(1,i,i) << "\n" ;
if ( num > 0 )
{
int l = max(i - k + 1,1ll) ;
int r = l + k - 1 ;
long long st = i - l + 1 ;
st = (num+st-1)/st ;
//cout << st << "\n" ;
add(1,l,r,-st) ;
ans += st ;
}
}
cout << ans << "\n" ;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
solve() ;
return 0 ;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)