Educational Codeforces Round 126

Educational Codeforces Round 126 ,第1张

题目

给你一个数组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抵消影响了吗,因为我们是从后往前,后面的数已经考虑过了。


AC代码
#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 ;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/607885.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-14
下一篇 2022-04-14

发表评论

登录后才能评论

评论列表(0条)

保存