当前位置: 首页 > article >正文

【最优清零方案——贪心+滑动窗口+线段树】

题目

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
int a[N];
struct node
{
    int l, r;
    int m, p, lazy;
} tr[4 * N];
void pushup(node &u, node &l, node &r)
{
    if (l.m == r.m)
    {
        u.m = l.m;
        u.p = max(l.p, r.p);
    }
    else if (l.m < r.m)
    {
        u.m = l.m;
        u.p = l.p;
    }
    else
    {
        u.m = r.m;
        u.p = r.p;
    }
}
void pushup(int u)
{
    pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void pushdown(node &u, node &l, node &r)
{
    if (u.lazy)
    {
        l.m = max(l.m + u.lazy, 0);
        r.m = max(r.m + u.lazy, 0);
        l.lazy += u.lazy;
        r.lazy += u.lazy;
        u.lazy = 0;
    }
}
void pushdown(int u)
{
    pushdown(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
    if (l == r)
        tr[u] = {l, r, a[l], l};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}
void modify(int u, int l, int r, int d)
{
    if (l <= tr[u].l && tr[u].r <= r)
    {
        tr[u].lazy += d;
        tr[u].m = max(tr[u].m + d, 0);
        return;
    }

    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if (l <= mid)
        modify(u << 1, l, r, d);
    if (r > mid)
        modify(u << 1 | 1, l, r, d);
    pushup(u);
}
node query(int u, int l, int r)
{
    if (l <= tr[u].l && tr[u].r <= r)
        return tr[u];

    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if (r <= mid)
        return query(u << 1, l, r);
    else if (l > mid)
        return query(u << 1 | 1, l, r);
    else
    {
        auto left = query(u << 1, l, r);
        auto right = query(u << 1 | 1, l, r);
        node ans;
        pushup(ans, left, right);
        return ans;
    }
}
int main()
{
    int n, k;
    cin >> n >> k;

    ll sum = 0;
    for (int i = 1; i <= n; i++)
        cin >> a[i], sum += a[i];

    build(1, 1, n);

    int l = 1, r;
    ll cnt = 0;
    while (r = l + k - 1, r <= n)
    {
        auto u = query(1, l, r);
        int minn = u.m;
        cnt += minn;
        modify(1, l, r, -minn);
        l = u.p + 1;
    }

    cout << sum - k * cnt + cnt;
}


http://www.kler.cn/a/407376.html

相关文章:

  • TIM输入捕获
  • 网页F12:缓存的使用(设值、取值、删除)
  • 远程控制软件使用教程
  • 使用bcc/memleak定位C/C++应用的内存泄露问题
  • uni-app打包H5自定义微信分享
  • 【eNSP】动态路由协议RIP和OSPF
  • [JLOI2014] 松鼠的新家(重链剖分+线段树)
  • Python完成达梦数据库备注到MySQL数据备注的脚本
  • 探索 .NET 9 控制台应用中的 LiteDB 异步 CRUD 操作
  • 141. Sprite标签(Canvas作为贴图)
  • 大数据新视界 -- 大数据大厂之 Impala 性能优化:融合人工智能预测的资源预分配秘籍(上)(29 / 30)
  • 电子应用设计方案-19:智能云饭锅系统方案设计
  • 039_SettingsGroup_in_Matlab图形界面的设置选项
  • Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
  • 网口输出的加速度传感器
  • 基于Java Springboot高校心理健康评测与服务系统
  • 【Linux】进程的基本概念
  • C++异常: cv::Exception 解决
  • 归一化/标准化对神经网络的训练是否有影响?
  • next build报错bash: next: command not found