题面

题目传送门

解法

从来没写过这样的……

  • 第一问非常简单,能够从 j j j转移到 i i i的条件显然为 a [ i ] − a [ j ] ≥ i − j a[i]-a[j]≥i-j a[i]−a[j]≥i−j,移项可得 a [ i ] − i ≥ a [ j ] − j a[i]-i≥a[j]-j a[i]−i≥a[j]−j。不妨令 x [ i ] = a [ i ] − i x[i]=a[i]-i x[i]=a[i]−i,那么在 O ( n log ⁡ n ) O(n\log n) O(nlogn)的复杂度内做最长不下降子序列就可以了。
  • 对于第二问,假设 g [ i ] g[i] g[i]为保留第 i i i个房子的最小花费,那么转移比较显然: g [ i ] = m i n { g [ j ] + ( 2 ∗ a [ j ] + i − j ) ( i − j − 1 ) 2 } + a [ i ] + b [ i ] g[i]=min\{g[j]+\frac{(2*a[j]+i-j)(i-j-1)}{2}\}+a[i]+b[i] g[i]=min{g[j]+2(2∗a[j]+i−j)(i−j−1)​}+a[i]+b[i]。把式子稍作化简一下可以得到 g [ i ] = m i n { g [ j ] − ( j + 1 ) a [ j ] + j ( j + 1 ) 2 + i ∗ x [ j ] } + a [ i ] + b [ i ] + i ( i − 1 ) 2 g[i]=min\{g[j]-(j+1)a[j]+\frac{j(j+1)}{2}+i*x[j]\}+a[i]+b[i]+\frac{i(i-1)}{2} g[i]=min{g[j]−(j+1)a[j]+2j(j+1)​+i∗x[j]}+a[i]+b[i]+2i(i−1)​。
  • 当然,能够从 j j j转移到 i i i的条件有三个:1. f [ j ] + 1 = f [ i ] f[j]+1=f[i] f[j]+1=f[i]; 2. x [ j ] ≤ x [ i ] x[j]≤x[i] x[j]≤x[i]; 3. j &lt; i j&lt;i j<i。
  • 简便起见,我们令 y [ i ] = g [ i ] − ( j + 1 ) a [ i ] + i ( i + 1 ) 2 y[i]=g[i]-(j+1)a[i]+\frac{i(i+1)}{2} y[i]=g[i]−(j+1)a[i]+2i(i+1)​。
  • 假设现在有两个决策点 j , k j,k j,k,并且 j j j更优,那么可以得到 y [ j ] + i ∗ x [ j ] &lt; y [ k ] + i ∗ x [ k ] y[j]+i*x[j]&lt;y[k]+i*x[k] y[j]+i∗x[j]<y[k]+i∗x[k],移项就可以变成 y [ j ] − y [ k ] &lt; i ( x [ k ] − x [ j ] ) y[j]-y[k]&lt;i(x[k]-x[j]) y[j]−y[k]<i(x[k]−x[j])。因为不知道 x [ j ] , x [ k ] x[j],x[k] x[j],x[k]的大小关系,我们不妨强制认为 x [ k ] &lt; x [ j ] x[k]&lt;x[j] x[k]<x[j],那么就可以得到 y [ j ] − y [ k ] x [ k ] − x [ j ] &gt; i \frac{y[j]-y[k]}{x[k]-x[j]}&gt;i x[k]−x[j]y[j]−y[k]​>i的关系。
  • 然后发现关系就变成了一个类似于斜率的式子,可以考虑斜率优化。
  • 可以将每一个决策点用 ( − x [ i ] , y [ i ] ) (-x[i],y[i]) (−x[i],y[i])的方式扔进坐标系内,显然,我们要得到的是一个下凸壳,那么类似于NOI2007货币兑换的做法,可以用cdq分治来维护这样一个下凸壳。
  • 然后考虑如何满足下标的几个限制。首先,我们可以分层进行dp,就是用 f [ i ] = t f[i]=t f[i]=t的点来更新 f [ i ] = t + 1 f[i]=t+1 f[i]=t+1的点。对于 x [ j ] ≤ x [ i ] x[j]≤x[i] x[j]≤x[i]和 j &lt; i j&lt;i j<i的限制在cdq分治中即可实现。
  • 在查询的时候直接在下凸壳上二分就可以了。
  • 时间复杂度: O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
template <typename T> void chkmax(T &x, T y) {x = x > y ? x : y;}
template <typename T> void chkmin(T &x, T y) {x = x > y ? y : x;}
template <typename T> void read(T &x) {x = 0; int f = 1; char c = getchar();while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
const int N = 100010; const ll inf = 1ll << 60;
int n, top, a[N], b[N], f[N], st[N]; ll g[N], x[N], y[N];
vector <int> v[N];
struct Node {int fl, id;bool operator < (const Node &q) const {return id < q.id;}
} q[N * 2];
bool cmp(int i, int j) {return (x[i] == x[j]) ? y[i] > y[j] : x[i] < x[j];}
double slope(int i, int j) {return 1.0 * (y[i] - y[j]) / (x[j] - x[i]);}
int calcf() {int len = 0;for (int i = 1; i <= n; i++) {if (x[i] < 0) {f[i] = n + 1; continue;}int l = 1, r = len, ans = 0;while (l <= r) {int mid = (l + r) >> 1;if (st[mid] <= x[i]) ans = mid, l = mid + 1;else r = mid - 1;}f[i] = ans + 1;if (ans == len) st[++len] = x[i]; else st[ans + 1] = x[i];}return len;
}
void query(int i) {if (!top) return;int l = 1, r = top - 1, j = st[top];while (l <= r) {int mid = (l + r) >> 1;if (slope(st[mid], st[mid + 1]) < i) j = st[mid], r = mid - 1;else l = mid + 1;}chkmin(g[i], g[j] + 1ll * (2 * a[j] + i - j) * (i - j - 1) / 2 + a[i] + b[i]);
}
void solve(int l, int r) {if (l == r) return;static int l1, l2, L[N], R[N];int mid = (l + r) >> 1;solve(l, mid), solve(mid + 1, r); top = l1 = l2 = 0;for (int i = l; i <= mid; i++) if (!q[i].fl) L[++l1] = q[i].id;for (int i = mid + 1; i <= r; i++) if (q[i].fl) R[++l2] = q[i].id;if (!l1 || !l2) return;sort(L + 1, L + l1 + 1, cmp), sort(R + 1, R + l2 + 1, cmp);for (int i = 1, j = 1; i <= l2; i++) {while (j <= l1 && x[L[j]] <= x[R[i]]) {if (top && x[st[top]] == x[L[j]]) top--;while (top >= 2 && slope(st[top - 1], st[top]) > slope(st[top], L[j])) top--;st[++top] = L[j++];}query(R[i]);}
}
int main() {read(n);for (int i = 1; i <= n; i++) read(a[i]), x[i] = a[i] - i;for (int i = 1; i <= n; i++) read(b[i]), g[i] = inf;int tx = calcf(); cout << tx << ' ';for (int i = 0; i <= n; i++) v[f[i]].push_back(i);for (int t = 0; t < tx; t++) {int len = 0;for (int i = 0; i < v[t].size(); i++) q[++len] = (Node) {0, v[t][i]};for (int i = 0; i < v[t + 1].size(); i++) q[++len] = (Node) {1, v[t + 1][i]};sort(q + 1, q + len + 1);solve(1, len);for (int i = 0; i < v[t + 1].size(); i++) {int j = v[t + 1][i];y[j] = -1ll * (j + 1) * a[j] + g[j] + 1ll * j * (j + 1) / 2;}}ll ans = inf;for (int i = 1; i <= n; i++)if (f[i] == tx) chkmin(ans, g[i] + 1ll * (2 * a[i] + n - i + 1) * (n - i) / 2);cout << ans << "\n";return 0;
}

bzoj 2149 拆迁队 斜率优化+cdq分治相关推荐

  1. BZOJ 2149 拆迁队 斜率优化DP 主席树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2149 题目大意: 一个长度为 n n的序列aa,改变其中的某些数使之成为一个单调递增序列, ...

  2. bzoj2149拆迁队 斜率优化dp+分治

    2149: 拆迁队 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 397  Solved: 177 [Submit][Status][Discuss ...

  3. ●BZOJ 2149 拆迁队

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2149 题解: 斜率优化DP,栈维护凸包,LIS,分治(我也不晓得是不是CDQ分治...) 一 ...

  4. 【BZOJ1492】[NOI2007]货币兑换Cash 斜率优化+cdq分治

    [BZOJ10492][NOI2007]货币兑换Cash Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下简称B券).每 ...

  5. 斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash

    Description Input 第一行两个正整数N.S,分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来N 行,第K 行三个实数AK.BK.RateK,意义如题目中所述 Output 只有 ...

  6. BZOJ 2149 拆迁队

    此题题意我一次读不清 , 是不是要完-- 题意: 给定一个数列, 修改其中的一些数,使得这个数列是严格递增的.并要求,修改的数尽量少(保留的数尽量多),并且代价尽量小. 代价的计算公式:修改完后所有数 ...

  7. bzoj1492 [NOI2007]货币兑换Cash (斜率DP+cdq分治)

    题意:到处都找得到. 我没看错的话当年考试的时候的题面里头,是提示了买卖一定是全部买入和卖出的.这样一来就好办了.cdq的论文里面那个F并不是她所说的那样,而是就是那个最优值.方程转移的时候实际上是枚 ...

  8. APIO2010 特别行动队 斜率优化DP算法笔记

    做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$ 可以变形为 $f[i]=max((a*sum[j ...

  9. YbtOJ#493-最大分数【斜率优化dp,分治】

    正题 题目链接:http://172.17.55.160/contest/117/problem/1 题目大意 nnn个数的一个序列,给其中的一些数打上标记. 一个标记方案的贡献为s1s_1s1​表示 ...

最新文章

  1. mysql generator 命令_MyBatis Generator速查手册
  2. 编写高性能的 Lua 代码
  3. 新地王的诞生终将付出惨痛的代价?
  4. Mysql表并联_SQL多表查询 表联结
  5. 使用BaseAdapter实现复杂的ListView
  6. 判断 Python 对象是否包含某个属性的方法
  7. ping不通Linux系统解决方法
  8. ios 网络状态获取_Network Kit X——网络检测工具箱
  9. 8102年底如何开发和维护一个npm项目
  10. 学编程决不可心浮气燥(转)
  11. 【NOIP2009】【codevs1174】靶形数独
  12. mvc:annotation-driven /注解意义
  13. 简单的MPI+Fortran95实现
  14. Java伪装csrss_csrss.exe是什么进程,是病毒吗?
  15. Java解压ZIP、RAR文件
  16. 游戏开发常遇到数据一致性BUG,怎么解?
  17. Rail-5k:一个用于轨道表面缺陷检测的真实数据集
  18. google 的高级搜索
  19. 操作系统中四步法实现PV操作
  20. strtodate mysql_MySQL str_to_date()函数

热门文章

  1. java乘方编程_30 个java编程技巧
  2. Room数据库简单使用
  3. matlab中出现未定义函数或变量如何解决?
  4. JS设计模式---(单例模式篇)
  5. Android Studio如何支持java8特性
  6. windows下Google Protocol Buffer 编译安装(vs)教程
  7. 在外远程查看家里内网监控
  8. pc机最低1MB主存空间的使用情况
  9. java 类加载 apk_在Android的App中动态的加载Java类
  10. CAD制图中如何合并两条线为一条线