Description:

lanxisi带领着他的拆迁队来整治一个街道。这个街道由N个旧房子组成,从左到右编号为1..N。每个旧房子i有一个正整数的美观度Ai。
  lanxisi希望整个街道从左到右美观度严格递增,也就是保证 Ai<Aj(i<j) Ai。但是旧的街道明显不符合这个要求,于是lanxisi希望拆迁一些旧房子并在原地建立新房子来满足这一要求。但是与很多拆迁队一样,很多钉子户拒绝拆迁。所以lanxisi希望能保留最多的旧房子来满足某些钉子户,当然,保留一个旧房子需要给房子主人Bi的赔偿金。最后,总花费=整治好以后所有房子美观度之和+赔偿金之和。新的美观值也都必须是正整数。
  现在,请你求出lanxisi最多能保留多少旧房子和整治这个街道所需要的最少总花费(当然是在保留旧房子最多这个前提下的)。
 1<=N<=100000,0<=Ai,Bi<=100000000。

:题解:

先思考最朴素的O(n^2)dp是如何运作的。

fi f_i是以i结尾最长不下降子序列的长度。
si s_i是以i结尾的最小总花费。

fi=max(fi+1)j<i,a[j]<a[i],a[j]−j<=a[i]−i) f_{i}=max(f_{i}+1)j
si=min(sj+…)(j<i,a[j]<a[i],a[j]−j<=a[i]−i,f[i]=f[j]+1) s_{i}=min(s_{j}+…)(j

如果有:
j<k,a[j]−j<=a[k]−k j
那么一定有:
a[j]<a[k] a[j]

所以可以去掉一个条件。

这样就可以可以用O(n log n)的时间按照a[i]-i为关键字dp出f。

接着按f分层dp。

打省略号的部分可以化成三部分:
1.和j有关的部分
2.和i有关的部分
3.(a[j]-j)*i

在同一层中,如果序号j递增,则a[j]-j递减,不然它们就不会在同一层。

所以满足斜率优化形式。

但是并没有这么简单。

注意条件除了a[j]-j<=a[i]-i,还有 j<i j

在分层后,序号并不是递增,高层的序号可能比低层小,而且a[j]-j同样只是在同一层内有序,不同层的大小关系无法判断。

简化问题后可以看作对一层的连续的一段j求
min(sj+(a[j]−j)∗i) min(s_{j}+(a[j]-j)*i)

到这里可以同线段树的分治思想来拆分询问。

对同一层建个线段树,每个点存这个点所代表的区间的j的单调栈。

因为线段树只有 log log层,每层最多n个,所以总共是 O(nlogn) O(n log n)。

接着把询问利用线段树拆成 log log段,每一段二分又是 log log,总复杂度是 O(nlog2n) O(n log^2 n)。

Code:

#include<cstdio>
#include<algorithm>
#define ll long long
#define ld long double
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
#define fd(i, x, y) for(ll i = x; i >= y; i --)
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;const ll N = 1e5 + 5;ll n, a[N], b[N], f[N], l[N], ml;
ll s[N], g[N], h[N];
ll final[N], next[N], to[N], tot;
ll st, en, ans;ld ji(ll k, ll b, ll l, ll r) {return (ld) (r - b) / (ld)(k - l);
}
ld jj(ll x, ll y) {return ji(h[x], g[x], h[y], g[y]);
}int d[N * 30], d0, z[N];
struct tree {int l, r;
} t[N * 4];void Build(int i, int x, int y) {t[i].l = d0 + 1; t[i].r = d0;fo(j, x, y) {while(t[i].l < t[i].r && jj(d[t[i].r - 1], d[t[i].r]) > jj(d[t[i].r], z[j]))t[i].r --;d[++ t[i].r] = z[j];}d0 = t[i].r;if(x == y) return;int m = x + y >> 1;Build(i + i, x, m); Build(i + i + 1, m + 1, y);
}ll xx;ll find(int i, int x, int y, int l, int r) {if(l > r) return 1e18;if(x == l && y == r) {int as = t[i].l;for(int p = t[i].l + 1, q = t[i].r; p <= q; ) {int m = p + q >> 1;if(jj(d[m - 1], d[m]) <= xx) as = m, p = m + 1; else q = m - 1; }return h[d[as]] * xx + g[d[as]];}int m = x + y >> 1;if(r <= m) return find(i + i, x, m, l, r);if(l > m) return find(i + i + 1, m + 1, y, l, r);ll p = find(i + i, x, m, l, m), q = find(i + i + 1, m + 1, y, m + 1, r);return min(p, q);
}int main() {scanf("%lld", &n);fo(i, 1, n) scanf("%lld", &a[i]);fo(i, 1, n) scanf("%lld", &b[i]);ml = 0; l[0] = 0;fo(i, 1, n) {if(a[i] - i < 0) {f[i] = 0; continue;}for(ll L = 1, r = ml; L <= r; ) {ll m = L + r >> 1;if(l[m] <= a[i] - i) f[i] = m, L = m + 1; else r = m - 1;}f[i] ++;if(f[i] > ml) l[++ ml] = a[i] - i;l[f[i]] = min(l[f[i]], a[i] - i);}fd(i, n, 1) next[++ tot] = final[f[i]], to[tot] = i, final[f[i]] = tot;fo(l, 1, ml) {z[0] = 0; d0 = 0;for(ll y = final[l - 1]; y; y = next[y])z[++ z[0]] = to[y];if(z[0]) Build(1, 1, z[0]);int st = 1, en = 0;for(ll ii = final[l]; ii; ii = next[ii]) {ll x = to[ii]; xx = x;while(en < z[0] && z[en + 1] < x) en ++;while(st <= en && a[z[st]] - z[st] > a[x] - x) st ++;s[x] = (a[x] - x >= 0 && l == 1) ? (b[x] + x * (x - 1) / 2) : 1e18;ll p = find(1, 1, z[0], st, en) + x * (x - 1) / 2 + b[x];s[x] = min(s[x], p);g[x] = s[x] - a[x] * x + (x + 1) * x / 2;h[x] = a[x] - x;}}ans = 1e18;fo(i, 1, n) if(f[i] == ml)ans = min(ans, s[i] + (n - i + 1) * a[i] + (n - i) * (n - i + 1) / 2);printf("%lld %lld", ml, ans);
}

【2011集训队出题】拆迁队相关推荐

  1. 【2011集训队出题】跳跳棋

    [2011集训队出题]跳跳棋 Time Limits: 1000 ms Memory Limits: 128000 KB Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点 ...

  2. JZOJ 1980. 【2011集训队出题】Construct

    Description 随着改革开放的深入推进-- 小T家要拆迁了-- 当对未来生活充满美好憧憬的小T看到拆迁协议书的时候,小T从一位大好的社会主义青年变成了绝望的钉子户. 由于小T的家位于市中心,拆 ...

  3. bzoj2144 [2011集训队出题] 跳跳棋 倍增 lca

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把 ...

  4. [国家集训队2011]拆迁队nbsp;解题报告

    题目: http://cogs.pro/cogs/problem/problem.php?pid=1859 lanxisi带领着他的拆迁队来整治一个街道.这个街道由N个旧房子组成,从左到右编号为1.. ...

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

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

  6. 【分治+斜率优化】BZOJ2149拆迁队 CF660F Bear and Bowling 4

    BZOJ2149拆迁队 [题目] 原题地址 题目大意不想写. [题目分析] 斜率优化的dp是显然的,然后就是怎么维护的问题了. [解题思路] 这题显然就是一个斜率优化的dp,然后分治的时候维护一下凸壳 ...

  7. chrome游戏:“钉子户大战拆迁队(Guard NailHoushold)”和“The Fancynbs

    查看原文:http://www.hellonet8.com/214.html 上个月chrome OS发布的时候,chrome 8 用户可以通过web store下载程序,自己就好奇进去下了些东西耍会 ...

  8. chrome游戏:“钉子户大战拆迁队(Guard NailHoushold)”和“The Fancy Pants Adventure: World 2”...

    上个月chrome OS发布的时候,chrome 8 用户可以通过web store下载程序,自己就好奇进去下了些东西耍会.好多程序就是简简单单的一个网页,可用性不怎么样,所以基本都被我卸载了.现在还 ...

  9. 《C#妹妹和Objective-C阿姨对话录》(04)垃圾回收基础--拆迁队那点事

    C#妹妹:操作系统天天说控制内存空间价格,咋还这么高?我巨资购买的内存空间,后来发现竟然在硬盘上!虚拟内存!TMD! Objective-C阿姨:操作系统全靠卖内存空间挣钱呢,你说价格能会降么?你看看 ...

最新文章

  1. 消除UITableView下面的额外分隔符
  2. js 实现2的n次方计算函数_密码杂凑函数的基本性质探讨
  3. LaTeX技巧24:LaTeX常用命令集锦
  4. 图像处理(十)基于特征线的图像变形-Siggraph 1992
  5. HLS实现点播和直播时,M3U8文件的不同
  6. java spark环境配置文件_JAVA, SCALA, HADOOP, SPARK里的JAVA_HOME和环境变量设置
  7. zabbix2.0安装与配置
  8. 鸿蒙安装elasticsearch7,安装操作系统_岁寒,然后知松柏之后凋也的技术博客_51CTO博客...
  9. element 手机适配_关于手机适配的方案(transform)
  10. Qt之QHeaderView自定义排序(获取正确的QModelIndex)
  11. Linux C代码实现读取配置文件示例
  12. springboot多环境配置_编辑 SpringBoot|第五章:多环境配置
  13. html 将光标移动到某行,如何将QTextBrowser(其中包含html表)的光标移动到PyQt5中的特定行?...
  14. 对 Lotus Notes 邮件模版进行二次开发的最佳实践
  15. 必读的Python入门书籍,你都看
  16. POJ_2828 Buy Ticket(线段树)
  17. 怎么下载卫星地图导出为离线包
  18. 三年经验前端vue面试记录
  19. VOC数据集格式介绍
  20. drwxr-xr-x是啥意思

热门文章

  1. Word 中公式居中,编号靠右
  2. 作为程序员,不要放弃英文学习
  3. 联想xp怎么打开无线网络连接服务器,ThinkPad如何使用windows网络管理器配置无线网络(XP)...
  4. vue组件之间通信(传值)---8种方式
  5. linux新建文件命令
  6. vue对手机号的判断_Vue分享功能实现,判断不同手机、浏览器及微信内核
  7. (转)java 数组转字符串 字符串转数组
  8. python绘制扇形代码_动态绘制扇形实例
  9. python取整的几种方法,Python中取整的几种方法小结
  10. scrapy——是否遵循爬虫规则