题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2149

题目大意:
一个长度为 n n的序列aa,改变其中的某些数使之成为一个单调递增序列,改变第 i i个数需要花费b[i]b[i]
求最多不改变的数的数量以及在这一条件下序列的总和 + +花费的最小值

题解:
首先可以令d[i]=a[i]−id[i]=a[i]-i,这样可以将单调递增转化为单调不下降更方便处理
设 f[i] f[i]表示到第 i i个数且不改变第ii个数时最多不改变多少个数
那么 f[i]=max{f[j]}+1(d[j]≤d[i]) f[i]=max\{f[j]\}+1(d[j] \le d[i])
设个 g[i] g[i]表示到第 i i个数且不改变第ii个数时序列总和 + +花费的最小值
那么g[i]=min{g[j]+d[j]∗(i−1−j)+(j+i)∗(i−1−j)2}+a[i](d[j]≤d[i],f[j]+1=f[i])g[i]=min\{g[j]+d[j]*(i-1-j)+\frac{(j+i)*(i-1-j)}{2}\}+a[i](d[j] \le d[i],f[j]+1=f[i])
整理一下发现可以斜率优化DP
x=−d[i] x=-d[i]
y=g[i]−a[i]∗(i+1)+i∗(i+1)2 y=g[i]-a[i]*(i+1)+\frac{i*(i+1)}{2}
k=i k=i
用一个主席树维护凸包,每次将一个点插到对应的节点中,更新时查询对应的区域

代码:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 100005
typedef long long ll;
int n;
int a[MAXN];
int b[MAXN];
ll c[MAXN];
int d[MAXN];
int e[MAXN];
int f[MAXN];
ll g[MAXN];
int cnt;
struct Point
{ll x,y;Point(ll _x=0,ll _y=0):x(_x),y(_y){}friend ll operator*(const Point &a,const Point &b){return a.x*b.y-a.y*b.x;}
};
vector<int>tr[MAXN*32];
int ls[MAXN*32],rs[MAXN*32];
int root[MAXN],tot;
void Update(int pos,int val,int l,int r,int &rt)
{if(!rt) rt=++tot;while(tr[rt].size()>1&&Point(-d[tr[rt][tr[rt].size()-1]]+d[tr[rt][tr[rt].size()-2]],c[tr[rt][tr[rt].size()-1]]-c[tr[rt][tr[rt].size()-2]])*Point(-d[val]+d[tr[rt][tr[rt].size()-1]],c[val]-c[tr[rt][tr[rt].size()-1]])<=0)tr[rt].pop_back();tr[rt].push_back(val);if(l==r) return;int mid=(l+r)>>1;if(pos<=mid) Update(pos,val,l,mid,ls[rt]);else Update(pos,val,mid+1,r,rs[rt]);
}
int Query(int R,int val,int l,int r,int rt)
{if(!rt) return -1;if(r<=R){if(!tr[rt].size()) return -1;int ll=0,rr=tr[rt].size()-1;while(rr-ll>2){int lmid=(ll+ll+rr)/3;int rmid=(ll+rr+rr)/3;if(c[tr[rt][lmid]]+1ll*val*d[tr[rt][lmid]]>c[tr[rt][rmid]]+1ll*val*d[tr[rt][rmid]]) ll=lmid;else rr=rmid;}int re=ll;for(int i=ll+1;i<=rr;i++)if(c[tr[rt][i]]+1ll*val*d[tr[rt][i]]<c[tr[rt][re]]+1ll*val*d[tr[rt][re]])re=i;return tr[rt][re];}int mid=(l+r)>>1;if(R<=mid) return Query(R,val,l,mid,ls[rt]);int re1=Query(R,val,l,mid,ls[rt]);int re2=Query(R,val,mid+1,r,rs[rt]);if(re1==-1) return re2;if(re2==-1) return re1;if(c[re1]+1ll*val*d[re1]<c[re2]+1ll*val*d[re2])return re1;else return re2;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",a+i);for(int i=1;i<=n;i++)scanf("%d",b+i);for(int i=1;i<=n;i++)d[i]=a[i]-i;f[0]=0;for(int i=1;i<=n;i++){if(d[i]<0){f[i]=-1;continue;}if(!cnt||e[cnt]<=d[i]) e[f[i]=++cnt]=d[i];else e[f[i]=upper_bound(e+1,e+1+cnt,d[i])-e]=d[i];}d[0]=0;g[0]=0;c[0]=0;Update(d[0],0,0,1000000000,root[f[0]]);for(int i=1;i<=n;i++){if(f[i]==-1){g[i]=0x3f3f3f3f3f3f3f3fll;continue;}int tmp=Query(d[i],i,0,1000000000,root[f[i]-1]);g[i]=c[tmp]+1ll*i*d[tmp]+1ll*i*(i-1)/2+a[i]+b[i];c[i]=g[i]-1ll*a[i]*(i+1)+1ll*i*(i+1)/2;Update(d[i],i,0,1000000000,root[f[i]]);}ll ans=0x3f3f3f3f3f3f3f3fll;for(int i=1;i<=n;i++)if(f[i]==cnt)ans=min(ans,g[i]+1ll*d[i]*(n-i)+1ll*(i+1+n)*(n-i)/2);printf("%d %lld\n",cnt,ans);return 0;
}

BZOJ 2149 拆迁队 斜率优化DP 主席树相关推荐

  1. bzoj 2149 拆迁队 斜率优化+cdq分治

    题面 题目传送门 解法 从来没写过这样的-- 第一问非常简单,能够从 j j j转移到 i i i的条件显然为 a [ i ] − a [ j ] ≥ i − j a[i]-a[j]≥i-j a[i] ...

  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. APIO2010 特别行动队 斜率优化DP算法笔记

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

  5. 「APIO2010」 特别行动队 - 斜率优化Dp

    题目描述 你有一支由nnn名预备役士兵组成的部队,士兵从1到nnn编号,要将他们拆分成若干特别行动队调入战场.出于默契考虑,同一支特别行动队中队员的编号应该连续,即为形如(i,i+1,...,i+k) ...

  6. 【bzoj1911】[Apio2010]特别行动队 斜率优化dp

    题目描述 输入 输出 样例输入 4 -1 10 -20 2 2 3 4 样例输出 9 题解 斜率优化dp 设f[i]表示前i个士兵的战斗力之和的最大值. 那么有f[i]=f[j]+a*(sum[i]- ...

  7. [APIO2010]特别行动队——[斜率优化DP]

    [题目描述] 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 n 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特别行动队中队员的编号 应该连续,即为形如(i,i+1,. ...

  8. BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]

    4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...

  9. BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 4142  Solved: 1964 [Submit][Sta ...

最新文章

  1. 解决Unity中新导入了C#文件在vs打开一直都是杂项文件的问题
  2. C语言执行Linux的shell命令并获得返回值
  3. 关联规则挖掘算法综述
  4. 3年后,基于mysql控制vsftp的用户认证机制
  5. python皮卡丘编程代码_Python高级编程-(Part 6 部署代码)
  6. paip.重装系统需要备份的资料总结..v2.0 cad
  7. 基于Unity的极乐净土/others MMD动画制作
  8. 使用CCS导出TXT用于BSL烧录
  9. “跨次元”检测模型hold住各种画风,真人赛博,在线Demo可玩
  10. 重写equals()方法
  11. 谷歌浏览器打开后是360导航界面解决办法
  12. NO7、斐波那契数列(easy不需再刷)
  13. 1. Pandas 导入导出数据
  14. 取消Chrome黑暗模式
  15. visio2007小技巧
  16. TypeScipt -回调函数
  17. 前端拖拽drag的使用
  18. 使用pycharm过程中出现This license K71U8DBPNE has been cancelled问题
  19. 某省财政厅12x4T私有云存储恢复
  20. Dive into TensorFlow - 解析 TF 核心抽象 op 算子

热门文章

  1. 项目管理中的冲突是什么?
  2. rust腐蚀网页游戏_腐蚀rust矿洞 | 手游网游页游攻略大全
  3. 忘了Excel 2003文档的密码怎么办
  4. kubernete编排技术二:deployment
  5. Java关键字super解释
  6. MSSQL2005_x64位标准版安装问题解决整理
  7. 江苏省2021年计算机二级考试成绩,2021年江苏省计算机等级考试分数公布时间|成绩查询入口...
  8. HTTP报文格式详细讲解
  9. 发布IonicAPP应用
  10. iOS/iPhoneOS Equalizer with libsox - doing some effects