题目描述

在炽热的核熔炉中,居住着一位少女,名为灵乌路空。

据说,从来没有人敢踏入过那个熔炉,因为人们畏缩于空所持有的力量——核能。

核焰,可融真金。

咳咳。

每次核融的时候,空都会选取一些原子,排成一列。然后,她会将原子序列分成一些段,并将每段进行一次核融。

一个原子有两个属性:质子数和中子数。

每一段需要满足以下条件:

1、同种元素会发生相互排斥,因此,同一段中不能存在两个质子数相同的原子。

2、核融时,空需要对一段原子加以防护,防护罩的数值等于这段中最大的中子数。换句话说,如果这段原子的中子数最大为x,那么空需要付出x的代价建立防护罩。求核融整个原子序列的最小代价和。

数据范围

对于20%的数据,1<=n<=100

对于40%的数据,1<=n<=1000

对于100%的数据,1<=n<=10^5,1<=pi<=n,1<=ni<=2*10^4

解法

动态规划;

设f[i]为在i与i+1之间切分最小代价和,那么f[n]就是答案。

f[i]=f[j]+max(a[j..i])

利用队列维护一个类似阶梯状,对于同一梯度,由于f递增,所以只需维护同一梯度最前的值。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="array.in";
const char* fout="array.out";
const int maxn=100007,maxt=maxn*4;
int n,i,j,k,v,LAST,inf;
int f[maxn],a[maxn][2];
int la[maxn],last[maxn];
int c[maxt];
void change(int l,int r,int t,int v,int v1){
int mid=(l+r)/2;
if (l==r){
c[t]=v1;
return;
}
if (v<=mid) change(l,mid,t*2,v,v1);
else change(mid+1,r,t*2+1,v,v1);
c[t]=min(c[t*2],c[t*2+1]);
}
int getmin(int l,int r,int t,int v1,int v2){
int mid=(l+r)/2;
if (l>v2 || r<v1) return inf;
if (l>=v1 && r<=v2) return c[t];
return min(getmin(l,mid,t*2,v1,v2),getmin(mid+1,r,t*2+1,v1,v2));
}
struct qual{
int data[maxn],id[maxn],head,tail;
qual(){
head=1;
tail=0;
}
void push(int v){
if (tail-head<0 || data[tail]!=0){
data[++tail]=0;
id[tail]=v;
change(1,n,1,tail,f[v]);
}
}
void pull(int v){
while (tail-head>=0 && data[tail]<v) tail--;
if (tail-head<0 || data[tail]>v){
tail++;
data[tail]=v;
change(1,n,1,tail,f[id[tail]]+data[tail]);
}
}
void update(int v,int v1){
while (tail-head>=1 && id[head+1]<v) head++;
if (tail-head>=0 && id[head]<v){
id[head]=v;
change(1,n,1,head,f[id[head]]+data[head]);
}
}
int top(){
return tail-head>=0?getmin(1,n,1,head,tail):inf;
}
}q;
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d",&n);
for (i=1;i<=n;i++){
scanf("%d%d",&a[i][0],&a[i][1]);
last[i]=la[a[i][0]];
la[a[i][0]]=i;
}
memset(f,127,sizeof(f));
memset(c,127,sizeof(c));
inf=c[0];
f[0]=0;
q.push(0);
for (i=1;i<=n;i++){
k=0;
LAST=max(LAST,last[i]);
q.update(LAST,i);
q.pull(a[i][1]);
f[i]=q.top();
q.push(i);
}
printf("%d",f[n]);
return 0;
}

启发

这道题演绎比较显然,很快会想出动态规划。

考虑答案的贡献,结合交集优化。

同一梯度的大多状态都是冗余的。

最新文章

  1. 1.13 linux笔记
  2. eclipse设置及快捷键
  3. HDU 1272 小希的迷宫(并查集)
  4. [AngularJS] Directive Definition Objects (DDO)
  5. python(6)-执行shell命令
  6. Android项目实战--手机卫士20--拿到已经安装了的程序以及程序管理主界面
  7. 那么温暖http合约,入门。
  8. GoogleGoogle搜索解析
  9. Spring学习(15)--- 基于Java类的配置Bean 之 @Bean &amp; @Scope 注解
  10. mybatis——分页插件
  11. 删除Widows 启动项中的信息
  12. 全网最详细的Windows里Anaconda-Navigator启动后闪退的解决方案(图文详解)
  13. Android UI(四)云通讯录项目之云端更新进度条实现
  14. Django中Form组件的使用
  15. Form的enctype属性
  16. python读取两个csv文件数据,进行查找匹配出现次数
  17. Eclipse 通过JPA自动生成注解实体
  18. 《杜增强讲Unity之Tanks坦克大战》1-准备工作
  19. python xlwt写excel格式控制 颜色、模式、编码、背景色
  20. 赶集网dba石展分享归纳

热门文章

  1. 【DM642学习笔记二】dsp基础实验:发光二级管的显示 led.c
  2. 10 种最常见的 Javascript 错误(频率最高)
  3. 2019-8-31-C++-驱动开发-error-LNK2019-unresolved-external-symbol-__CheckForDebuggerJustMyCode-referenced-...
  4. 系统io统计
  5. 配置android studio环境
  6. bzoj 1800 [Ahoi2009]fly 飞行棋——模拟
  7. TZ_06_SpringMVC_传统文件上传和SpringMVC文件上传方式
  8. 移动端 Iphone拍照变横问题的解决
  9. Hackerrank--Mixing proteins(Math)
  10. ucore os 前初始化