首页 > 其他分享 >P11103 [ROI 2022 Day 2] 挑战

P11103 [ROI 2022 Day 2] 挑战

时间:2024-11-13 22:29:26浏览次数:1  
标签:ROI int void mid tag P11103 data Day fill

题目可以看成一个最大流模型。源点 \(S\) 往所有机器人连边,容量为 \(c_i\);所有容器往汇点 \(T\) 连边,容量为 \(a_i\);机器人 \(i\) 往容器 \(j\in[l_i,r_i]\) 连边,容量 \(+\infty\)。最大流即为答案。

最大流不好计算,考虑最小割。不妨令选取容器集合为 \(S\),不被 \(S\) 包含的区间都必须割掉,于是代价为 \(\sum\limits_{x\in S}a_x+\sum\limits_{i=1}^m[[l_i,r_i]\nsubseteq S]c_i\) 。

这个可以考虑 dp,\(f_{i,j}\) 表示考虑前 \(i\) 个容器,最后一个未选的为 \(j\),最小代价。转移类似 AT_dp_w,可以线段树维护做到单次 \(O(n\log n)\)。

考虑 \(t_i=1\) 怎么算。可以发现,此时 \(S\) 可以表示为一个区间 \([L,R]\) 且满足 \(L\le x\le R\)。对 \(L\) 扫描线,维护历史 \(\min\) 即可。

现在存在 \(t_i=0\),仍然考虑取出 \(S\) 中极大的区间 \([L,R]\) 满足 \(L\le x\le R\)。那么代价可以拆成 \([1,L-1],[L,R],[R+1,n]\) 三个区间的贡献。前缀可以用上面的 dp 预处理 \(F_i\),后缀同理,记为 \(G_i\)。

中间部分考虑分讨 \(t=0\) 还是 \(1\):

  • \(t_i=0\):\([l_i,r_i]\) 与 \([L,R]\) 有交且不被包含时被计入代价;
  • \(t_i=1\):\([l_i,r_i]\) 只要不包含于 \([L,R]\) 即可。

这两个部分都可以扫描线,线段树维护历史 \(\min\),可以做到 \(O(n\log n)\)。

code
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
void file() {
  freopen("1.in", "r", stdin);
  freopen("1.out", "w", stdout);
}
using ll = long long;

const ll kInfl = 1e18, kInf = 1e9;
const int kN = 2e5 + 5, kS = 1e6 + 5;

int n, m;
array<int, kN> a;
array<ll, kN> prea, ans;

struct Bot {
  int l, r, c, type;
  Bot() { }
};
array<Bot, kN> bot;

namespace TYPE0 {
  namespace SGT {
    array<ll, kS> tag, mn;

    void clear() {
      fill_n(tag.data(), 4 * (n + 10), 0);
      fill_n(mn.data(), 4 * (n + 10), kInfl);
    }
    void pu(int o) { mn[o] = min(mn[ls], mn[rs]); }
    void ad(int o, ll v) { mn[o] += v; tag[o] += v; }
    void pd(int o) {
      if(ll& x = tag[o])
        ad(ls, x), ad(rs, x), x = 0;
    }
    void modify(int o, int l, int r, int x, ll v) {
      if(l == r) return void(mn[o] = v);
      pd(o); int mid = (l + r) >> 1;
      if(mid < x) modify(rs, mid + 1, r, x, v);
      else modify(ls, l, mid, x, v);
      pu(o);
    }
    void update(int o, int l, int r, int x, int y, ll v) {
      if((l > y) || (r < x)) return ;
      if((l >= x) && (r <= y)) return ad(o, v);
      pd(o); int mid = (l + r) >> 1;
      update(ls, l, mid, x, y, v);
      update(rs, mid + 1, r, x, y, v);
      pu(o);
    }
    ll query() { return mn[1]; }
  }

  array<ll, kN> F, G;

  void clear() {
    fill_n(F.data(), n + 2, kInfl);
    fill_n(G.data(), n + 2, kInfl);
  }
  void solvef() {
    sort(bot.data() + 1, bot.data() + m + 1, [&](Bot x, Bot y) { return x.r < y.r; });
    F[0] = 0;
    SGT::clear(), SGT::modify(1, 0, n, 0, 0);
    for(int i = 1, j = 1; i <= n; i++) {
      ll val = SGT::query();
      SGT::modify(1, 0, n, i, val);
      SGT::update(1, 0, n, 0, i - 1, a[i]);
      for(; (j <= m) && (bot[j].r == i); j++)
        if(!bot[j].type)
          SGT::update(1, 0, n, bot[j].l, i, bot[j].c);
      F[i] = SGT::query();
    }
  }
  void solveg() {
    sort(bot.data() + 1, bot.data() + m + 1, [&](Bot x, Bot y) { return x.l > y.l; });
    G[n + 1] = 0;
    SGT::clear(), SGT::modify(1, 1, n + 1, n + 1, 0);
    for(int i = n, j = 1; i; i--) {
      ll val = SGT::query();
      SGT::modify(1, 1, n + 1, i, val);
      SGT::update(1, 1, n + 1, i + 1, n + 1, a[i]);
      for(; (j <= m) && (bot[j].l == i); j++)
        if(!bot[j].type)
          SGT::update(1, 1, n + 1, i, bot[j].r, bot[j].c);
      G[i] = SGT::query();
    }
  }
  void solve() { clear(), solvef(), solveg(); }
}

namespace TYPE_ALL {
  namespace A {
    array<ll, kN> dif;

    void clear() { fill_n(dif.data(), n + 1, 0); }
    void solve() {
      clear();
      ll sum1 = 0;
      for(int i = 1; i <= m; i++)
        if(bot[i].type) sum1 += bot[i].c;
        else {
          dif[bot[i].l] += bot[i].c;
          dif[bot[i].r + 1] -= bot[i].c;
        }
      for(int i = 1; i <= n; i++) dif[i] += dif[i - 1];
      for(int i = 1; i <= n; i++)
        ans[i] = dif[i] + sum1 + TYPE0::F[i - 1] + TYPE0::G[i + 1];
    }
  }

  namespace B {
    namespace SGT {
      struct Info {
        ll mn, h;
        Info() { mn = h = kInfl; }
        Info(ll _mn, ll _h) { mn = _mn; h = _h; }
      };
      Info operator + (const Info& x, const Info& y) {
        return Info(min(x.mn, y.mn), min(x.h, y.h));
      }

      struct Tag {
        ll a00, a01, a11;
        Tag() { a00 = a11 = 0; a01 = kInfl; }
        Tag(ll _a00, ll _a01, ll _a11) {
          a00 = _a00; a01 = _a01; a11 = _a11;
        }
        bool empty() { return !a00 && !a11 && (a01 == kInfl); }
      };
      Tag& operator += (Tag& x, const Tag& y) {
        Tag ans;
        ans.a00 = x.a00 + y.a00;
        ans.a01 = min(x.a00 + y.a01, x.a01 + y.a11);
        ans.a11 = x.a11 + y.a11;
        return x = ans;
      }
      Info& operator += (Info& x, const Tag& y) {
        x.h = min(x.mn + y.a01, x.h + y.a11);
        x.mn += y.a00;
        return x;
      }

      array<Info, kS> sum;
      array<Tag, kS> tag;

      void clear() {
        fill_n(sum.data(), 4 * (n + 10), Info());
        fill_n(tag.data(), 4 * (n + 10), Tag());
      }
      void pu(int o) { sum[o] = sum[ls] + sum[rs]; }
      void build(int o, int l, int r, ll* val) {
        if(l == r)
          return void(sum[o] = Info(val[l], val[l]));
        int mid = (l + r) >> 1;
        build(ls, l, mid, val);
        build(rs, mid + 1, r, val);
        pu(o);
      }
      void ad(int o, const Tag& t) { sum[o] += t; tag[o] += t; }
      void pd(int o) {
        if(!tag[o].empty())
          ad(ls, tag[o]), ad(rs, tag[o]), tag[o] = Tag();
      }
      void update(int o, int l, int r, int x, int y, Tag t) {
        if((l > y) || (r < x)) return ;
        if((l >= x) && (r <= y)) return ad(o, t);
        pd(o); int mid = (l + r) >> 1;
        update(ls, l, mid, x, y, t);
        update(rs, mid + 1, r, x, y, t);
        pu(o);
      }
      ll query(int o, int l, int r, int x, int y) {
        if((l > y) || (r < x)) return kInfl;
        if((l >= x) && (r <= y)) return sum[o].h;
        pd(o); int mid = (l + r) >> 1;
        return min(query(ls, l, mid, x, y), query(rs, mid + 1, r, x, y));
      }
      void add(int l, int r, ll v) { update(1, 1, n, l, r, Tag(v, kInfl, 0)); }
      void updateh() { ad(1, Tag(0, 0, 0)); }
    }

    array<ll, kN> val;
    array<vector<int>, kN> buc0L, buc0R, buc1;

    void clear() {
      SGT::clear();
      fill_n(val.data(), n + 1, 0);
      fill_n(buc0L.data(), n + 1, vector<int> ());
      fill_n(buc0R.data(), n + 1, vector<int> ());
      fill_n(buc1.data(), n + 1, vector<int> ());
    }
    void init() {
      for(int i = 1; i <= m; i++) {
        if(!bot[i].type) {
          if(bot[i].l != bot[i].r) {
            val[bot[i].l] += bot[i].c;
            val[bot[i].r] -= bot[i].c;
            buc0L[bot[i].l].push_back(i);
            buc0R[bot[i].r].push_back(i);
          }
        }else {
          val[1] += bot[i].c;
          val[bot[i].r] -= bot[i].c;
          buc1[bot[i].l].push_back(i);
        }
      }
      for(int i = 1; i <= n; i++) val[i] += val[i - 1];
      for(int i = 1; i <= n; i++)
        val[i] += prea[i] + TYPE0::G[i + 1];
      SGT::build(1, 1, n, val.data());
    }
    void solve() {
      clear(), init();
      for(int i = 1; i <= n; i++) {
        ans[i] = min(ans[i], SGT::query(1, 1, n, i, n));
        SGT::add(i + 1, n, -a[i]);
        for(int j : buc0L[i]) SGT::add(bot[j].r, n, bot[j].c);
        for(int j : buc0R[i]) SGT::add(i + 1, n, -bot[j].c);
        for(int j : buc1[i]) SGT::add(bot[j].r, n, bot[j].c);
        SGT::add(i + 1, n, TYPE0::F[i] - TYPE0::F[i - 1]);
        SGT::updateh();
      }
    }
  }

  void solve() { A::solve(), B::solve(); }
}

void solve() {
  cin >> n >> m;
  for(int i = 1; i <= n; i++)
    cin >> a[i], prea[i] = prea[i - 1] + a[i];
  for(int i = 1; i <= m; i++)
    cin >> bot[i].l >> bot[i].r >> bot[i].c >> bot[i].type;
  TYPE0::solve(), TYPE_ALL::solve();
  for(int i = 1; i <= n; i++)
    cout << ans[i] << " \n" [i == n];
}

int main() {
  // file();
  ios::sync_with_stdio(0), cin.tie(0);
  int T = 1;
  cin >> T;
  while(T--) solve();
  return 0;
}

标签:ROI,int,void,mid,tag,P11103,data,Day,fill
From: https://www.cnblogs.com/cjoierzdc/p/18544978

相关文章

  • 代码随想录算法训练营day45| 115.不同的子序列 583. 两个字符串的删除操作 72.
    学习资料:https://programmercarl.com/0115.不同的子序列.html#算法公开课动态规划系列之编辑距离问题学习记录:115.不同的子序列(当遇到相同字母时,可以选择也可以不选;刚开始没看懂;dp[i][j]是对应i-1结尾和j-1结尾,这样的目的是方便第一行和第一列初始化)点击查看代码classSolut......
  • 微服务day07
    Elasticsearch 需要安装elasticsearch和Kibana,应为Kibana中有一套控制台可以方便的进行操作。安装elasticsearch使用docker命令安装:dockerrun-d\--namees\-e"ES_JAVA_OPTS=-Xms512m-Xmx512m"\//设置他的运行内存空间,不要低于512否则出问题-e"disc......
  • 基于springboot+vue的Android的党员之家服务APP小程序(源码+文档+部署讲解等)
    课题简介本党员之家服务APP基于springboot+vue技术开发,专为Android平台设计,涵盖源码、文档和部署讲解,为党员们提供便捷、高效的服务。在资讯功能方面,APP会及时推送党的最新理论成果、政策解读、重要会议精神等内容,让党员能够第一时间了解党和国家的政治动态。同......
  • Facebook广告投放:快速提高ROI的8个关键方法
    Facebook广告在海外数字营销中占据重要地位。据统计,约有700万广告商活跃在该平台上,购买力不容小觑。然而,当前Facebook广告竞争激烈,导致广告位供不应求,成本上升,尤其是在下半年营销旺季中,广告主广告需求明显增加,推高了广告成本。那么如何在有限的预算中跑出理想的ROI,本篇内......
  • 快速提升ROI,收藏这份Facebook广告投放技巧!
    Facebook广告在海外数字营销中占据重要地位。据统计,约有700万广告商活跃在该平台上,购买力不容小觑。然而,当前Facebook广告竞争激烈,导致广告位供不应求,成本上升,尤其是在下半年营销旺季中,广告主广告需求明显增加,推高了广告成本。那么如何在有限的预算中跑出理想的ROI,本篇内......
  • 团队项目Scrum冲刺-day3
    一、每天举行站立式会议站立式会议照片一张昨天已完成的工作成员任务陈国金用户模块的部分接口凌枫用户登录页面陈卓恒用户注册界面谭立业题目搜索页面部分内容廖俊龙接口测试曾平凡前端页面测试曾俊涛题目模块的部分接口薛秋昊题目提......
  • UOJ NOI Round #7 Day1 比特迷宫 个人记录
    思路构造,且上界并不是特别严格。/bx/bx/bx首先加法比较“混合”,考虑转成位运算,具体地,钦定操作的\(a,b\)满足\(a\&b=0\)。考虑递归成子问题,按照popcount分组,有一个关键观察是:我们在操作一个\(a|b=c\)的时候,可以将任意几个\(d\&c=d\)且\(popcount(d)=popcount......
  • Day6
    Day6当天站立式会议照片团队成员姓名学号昨天已完成的工作今天计划完成的工作工作中遇到的困难林涛(组长)3122004618测试api完成后台模块null杨森3122004629完成家长模块完成后台模块后台模块的事物操作钟礼骏3122006504完成家长模块完成家长模块......
  • Day7
    Day7当天站立式会议照片团队成员(完成所有功能在测试)姓名学号昨天已完成的工作今天计划完成的工作工作中遇到的困难林涛(组长)3122004618完成后台模块测试null杨森3122004629完成后台模块测试null钟礼骏3122006504完成家长模块测试null许佳......
  • Vue: Day_2
    Vue基础Chapter2当想获取父组件传递的属性或者值时但是不通过define方法$attrs获取父组件传递的属性如:<Childclass="child"/>,可以通过$attrs.class获取如果控制输入类或者点击类的DOM,但是又是父组件传递处理函数这是就需要$emit(handleFn,$event)来访问到父组件传......