题目

题目在这里

思路&做法

明显的最小割(其实是之前做过一道类似的题)

  1. S向每一个格子连容量为\(b_i\)的边

  2. 每一个格子向T连容量为\(w_i\)的边

  3. 对于格子\(i\)向满足条件的格子\(j(1 \leq j < i, l_i \leq a_j \leq r_i)\)连容量为\(p_i\)的边

但是考虑到这题恶心的数据范围, 这样做很明显会TLE。

算法的瓶颈在第三步。我们发现\(j\)的范围看起来像是一个像二维偏序的东西, 于是便可以用主席树来优化一下, 对于每个节点\(i\)新建一个节点\(k\),由i向k连容量为\(p_i\)的边, 由\(k\)向主席树中\(j\)的范围的对应的节点连容量为\(inf\)的边。

代码

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <cmath>
  6. #include <queue>
  7. #include <vector>
  8. #include <algorithm>
  9. using namespace std;
  10. const int INF = 0x7F7F7F7F;
  11. const int N = 50010, M = 1450010;
  12. struct edge
  13. { int from, to, flow, cap;
  14. edge() { }
  15. edge(int _1, int _2, int _3, int _4) : from(_1), to(_2), flow(_3), cap(_4) { }
  16. };
  17. struct Dinic
  18. { edge edges[M];
  19. int head[165022], nxt[M], tot;
  20. int L, R;
  21. inline void init()
  22. { memset(head, -1, sizeof(head));
  23. tot = 0;
  24. }
  25. void add_edge(int x, int y, int z)
  26. { edges[tot] = edge(x, y, 0, z);
  27. nxt[tot] = head[x];
  28. head[x] = tot++;
  29. edges[tot] = edge(y, x, 0, 0);
  30. nxt[tot] = head[y];
  31. head[y] = tot++;
  32. }
  33. int s, t;
  34. int d[165022];
  35. bool bfs()
  36. { memset(d, -1, sizeof(d));
  37. queue<int> q;
  38. d[s] = 0;
  39. q.push(s);
  40. while (!q.empty())
  41. { int x = q.front(); q.pop();
  42. for (int i = head[x]; ~i; i = nxt[i])
  43. { edge & e = edges[i];
  44. if (e.cap > e.flow && d[e.to] == -1)
  45. { d[e.to] = d[x] + 1;
  46. q.push(e.to);
  47. }
  48. }
  49. }
  50. return d[t] != -1;
  51. }
  52. int cur[165022];
  53. int dfs(int x, int a)
  54. { if (x == t || a == 0) return a;
  55. int flow = 0, f;
  56. for (int & i = cur[x]; ~i; i = nxt[i])
  57. { edge & e = edges[i];
  58. if (d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap-e.flow))) > 0)
  59. { e.flow += f;
  60. edges[i^1].flow -= f;
  61. a -= f;
  62. flow += f;
  63. if (a == 0) break;
  64. }
  65. }
  66. return flow;
  67. }
  68. int maxflow(int _s, int _t)
  69. { s = _s, t = _t;
  70. int flow = 0;
  71. while (bfs())
  72. { for (int i = L; i <= R; i++)
  73. cur[i] = head[i];
  74. flow += dfs(s, INF);
  75. }
  76. return flow;
  77. }
  78. } dinic;
  79. int n;
  80. int root[N];
  81. struct SegmentTree
  82. { int ls[N*20], rs[N*20], sz;
  83. void update(int & cur, int pre, int l, int r, int p, int node)
  84. { cur = ++sz;
  85. if (l == r)
  86. { if (pre) dinic.add_edge(cur, pre, INF);
  87. dinic.add_edge(cur, node, INF);
  88. return;
  89. }
  90. ls[cur] = ls[pre];
  91. rs[cur] = rs[pre];
  92. int mid = (l + r) >> 1;
  93. if (p <= mid)
  94. update(ls[cur], ls[pre], l, mid, p, node);
  95. else
  96. update(rs[cur], rs[pre], mid+1, r, p, node);
  97. dinic.add_edge(cur, ls[cur], INF);
  98. dinic.add_edge(cur, rs[cur], INF);
  99. }
  100. void link(int cur, int l, int r, int ql, int qr, int node)
  101. { if (ql == l && qr == r)
  102. dinic.add_edge(node, cur, INF);
  103. else
  104. { int mid = (l + r) >> 1;
  105. if (qr <= mid)
  106. link(ls[cur], l, mid, ql, qr, node);
  107. else if (ql > mid)
  108. link(rs[cur], mid+1, r, ql, qr, node);
  109. else
  110. link(ls[cur], l, mid, ql, mid, node),
  111. link(rs[cur], mid+1, r, mid+1, qr, node);
  112. }
  113. }
  114. } st;
  115. int a[N], w[N], b[N], L[N], R[N], p[N];
  116. int num[N], total;
  117. int main()
  118. { scanf("%d", &n);
  119. for (int i = 1; i <= n; i++)
  120. { scanf("%d %d %d %d %d %d", &a[i], &b[i], &w[i], &L[i], &R[i], &p[i]);
  121. num[++total] = a[i];
  122. num[++total] = L[i];
  123. num[++total] = R[i];
  124. }
  125. sort(num+1, num+total+1);
  126. total = unique(num+1, num+total+1) - num - 1;
  127. for (int i = 1; i <= n; i++)
  128. { a[i] = lower_bound(num+1, num+1+total, a[i]) - num;
  129. L[i] = lower_bound(num+1, num+1+total, L[i]) - num;
  130. R[i] = lower_bound(num+1, num+1+total, R[i]) - num;
  131. }
  132. int ans = 0;
  133. dinic.init();
  134. int S = n + n + 1, T = n + n + 2;
  135. st.sz = n + n + 2;
  136. for (int i = 1; i <= n; i++)
  137. { dinic.add_edge(S, i, b[i]);
  138. dinic.add_edge(i, T, w[i]);
  139. dinic.add_edge(i, i+n, p[i]);
  140. if (i > 1)
  141. st.link(root[i-1], 1, total, L[i], R[i], i+n);
  142. st.update(root[i], root[i-1], 1, total, a[i], i);
  143. ans += b[i] + w[i];
  144. }
  145. dinic.L = 0, dinic.R = st.sz;
  146. ans -= dinic.maxflow(S, T);
  147. printf("%d\n", ans);
  148. }
  149. /*
  150. 10
  151. 0 1 7 3 9 2
  152. 7 4 0 9 10 5
  153. 1 0 4 2 10 2
  154. 7 9 1 5 7 2
  155. 6 3 5 3 6 2
  156. 6 6 4 1 8 1
  157. 6 1 6 0 6 5
  158. 2 2 5 0 9 3
  159. 5 1 3 0 2 5
  160. 5 6 7 1 1 2
  161. */

【BZOJ3218】【UOJ#77】a + b Problem的更多相关文章

  1. 【UOJ#77】A+B Problem

    传送门 题目描述 略 Sol 看到选择黑白收益不同,然后还可能有代价. 我们想到用网络流解决,并且这应该是用总可能收益-最小割得到答案. 考虑初步建图,发现那个限制可以直接 \(n^2\) 解决. 我 ...

  2. 【UOJ#236】[IOI2016]railroad(欧拉回路,最小生成树)

    [UOJ#236][IOI2016]railroad(欧拉回路,最小生成树) 题面 UOJ 题解 把速度看成点,给定的路段看成边,那么现在就有了若干边,然后现在要补上若干边,以及一条\([inf,\) ...

  3. 【UOJ#177】欧拉回路

    [UOJ#177]欧拉回路 题面 UOJ 题解 首先图不连通就没啥好搞的了. 对于无向图而言,每个点度数为偶数. 对于有向图而言,每个点入度等于出度. 然后就是一本通上有的做法,直接\(dfs\)一遍 ...

  4. 【UOJ#311】【UNR #2】积劳成疾(动态规划)

    [UOJ#311][UNR #2]积劳成疾(动态规划) UOJ Solution 考虑最大值分治解决问题.每次枚举最大值所在的位置,强制不能跨过最大值,左右此时不会影响,可以分开考虑. 那么设\(f[ ...

  5. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  6. 【UOJ#246】套路(动态规划)

    [UOJ#246]套路(动态规划) 题面 UOJ 题解 假如答案的选择的区间长度很小,我们可以做一个暴力\(dp\)计算\(s(l,r)\),即\(s(l,r)=min(s(l+1,r),s(l,r- ...

  7. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  8. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  9. 【UOJ#275】组合数问题(卢卡斯定理,动态规划)

    [UOJ#275]组合数问题(卢卡斯定理,动态规划) 题面 UOJ 题解 数据范围很大,并且涉及的是求值,没法用矩阵乘法考虑. 发现\(k\)的限制是,\(k\)是一个质数,那么在大组合数模小质数的情 ...

随机推荐

  1. 时序分析:串匹配—Brute-Force算法

    在使用KMP算法之前,使用了BF算法用于串匹配:原文链接已无法查找.....        设有主串s和子串t,子串t的定位就是要在主串s中找到一个与子串t相等的子串.通常把主串s称为目标串,把子串t ...

  2. 【ng-zorro-antd】加入in-memory-web-api插件后icon不显示

    在ng-zorro-antd框架下,根据angular的技术文档demo,加入in-memory-web-api后icon不显示 解决方案: 在app.module.ts中的imports:[]加入 ...

  3. 【剑指Offer】54、字符流中第一个不重复的字符

      题目描述:   请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字 ...

  4. 分别用for循环,while do-while以及递归方法实现n的阶乘!

    分别用for循环,while do-while以及递归方法实现n的阶乘! 源码: package book;import java.util.Scanner;public class Access { ...

  5. 数据结构实验病毒感染检测问题(C++)

    医学研究者最近发现了某些新病毒,通过对这些病毒的分析,得知他们的DNA序列都是环状的.现在研究者已收集了大量的病毒DNA和人的DNA数据,想快速检测出这些人是否感染了相应的病毒.为了方便研究,研究者将 ...

  6. 在LinuxMint19上安装搜狗拼音输入法

    写在前面 由于Linux mint是基于Ubuntu的深度改造,所以按照网上针对Ubuntu的安装方法基本都是有用的.LinuxMint自身就携带了IBUS和fcitx两个框架.然而并非每次都能正常使 ...

  7. Nginx服务(端口80)

    Nginx安装: 一.编译安装 1.安装相应软件 yum install pcre pcre-devel openssl openssl-devel -y 2.检查: rpm -aq pcre pcr ...

  8. Linux思维导图之sed、实战习题

    命令解释: ◆sed 2p /etc/passwd第二行打印了两次其余一次 ◆sed-n '2p' /etc/passwd 只打印出第二行 ◆sed-n 1,4p' /etc/passwd 只打印出1 ...

  9. 微信系列之公众号Token验证

    微信系列之公众号Token验证 pycharm连接线上服务器开发 开发过程笔记 参考资料 python3安装web.py可以选择安装`pip install web.py==0.40.dev0 pyc ...

  10. 解决ICS40上设置APN无权限问题

    在ICS40以前的版本中,如果程序需要设置APN,只需要在AndroidManifest文件中声明<uses-permission android:name="android.perm ...