https://codeforces.com/contest/1131/problem/G

题意

给你一排m个的骨牌(m<=1e7),每块之间相距1,每块高h[i],推倒代价c[i],假如\(abs(i-j)<h[i]\),那么向j方向推倒i,j也会倒,问选择任意数量骨牌向任意方向推到,使得全部骨牌都倒下的代价最小

题解

  • 连锁反应可以用单调栈或者链表模拟
  • 定义dp[i]为推倒a[i,m]的最小代价
  • 对于每个i,有两种选择:
    • 向左推:\(dp[l[i]+1]=min(dp[l[i]+1],dp[i+1]+c[i])\)
    • 向右推:\(dp[i]=min(dp[i],rf[i]+c[i]),rf[i]\),\(rf[i]\)为推倒i能到达的位置上最小dp值
  • 单调栈写法很难懂

代码

链表写法
#include<bits/stdc++.h>
#define ll long long
#define mxN 300005
#define mxM 10000005
#define inf 0x3f3f3f3f
using namespace std;
ll n,m,i,j,k,N,q,x,y,p;
int l[mxM],h[mxM],r[mxM];
vector<array<int,2>>a[mxN];
ll rf[mxM],f[mxM],c[mxM]; int main(){
cin>>n>>m;
for(i=0;i<n;i++){
scanf("%lld",&N);
a[i].resize(N);
for(j=0;j<2;j++)
for(k=0;k<N;k++)
scanf("%d",&a[i][k][j]);
}
cin>>q;
for(i=0;i<q;i++){
scanf("%lld%lld",&x,&y);
for(j=0;j<a[x-1].size();j++,p++){
h[p]=a[x-1][j][0];
c[p]=a[x-1][j][1]*y;
l[p]=p-1;
while(l[p]>=0&&p-l[p]<h[p])
l[p]=l[l[p]];
}
}
memset(f,inf,sizeof(f));
f[m]=0;
for(i=m-1;i>=0;i--){
rf[i]=f[i+1];
r[i]=i+1;
while(r[i]<m&&r[i]-i<h[i]){
rf[i]=min(rf[r[i]],rf[i]);
r[i]=r[r[i]];
}
f[l[i]+1]=min(f[l[i]+1],f[i+1]+c[i]);
f[i]=min(f[i],rf[i]+c[i]);
}
cout<<f[0];
}

单调栈写法

#include<bits/stdc++.h>
#define ll long long
#define mxN 300005
#define mxM 10000005
#define inf 0x3f3f3f3f
using namespace std;
ll n,m,i,j,k,N,q,x,y,p,l,r;
int h[mxM],cnt[mxM];
vector<array<int,2>>a[mxN];
ll rf[mxM],f[mxM],c[mxM],val; int main(){
cin>>n>>m;
for(i=0;i<n;i++){
scanf("%lld",&N);
a[i].resize(N);
for(j=0;j<2;j++)
for(k=0;k<N;k++)
scanf("%d",&a[i][k][j]);
}
cin>>q;
for(i=0;i<q;i++){
scanf("%lld%lld",&x,&y);
for(j=0;j<a[x-1].size();j++){
h[++p]=a[x-1][j][0];
c[p]=a[x-1][j][1]*y;
}
}
stack<array<ll,2>>s1;
stack<ll>s2;
s1.push({m+1,0});
s2.push(1e17);
//memset(f,inf,sizeof(f));
for(i=m;i>=1;i--){
r=min(m,i+h[i]-1);
while(r>=s1.top()[0])s1.pop();
cnt[s1.top()[0]-1]++;
s1.push({i,0});
}
while(!s1.empty())s1.pop();
s1.push({0,0});
for(i=1;i<=m;i++){
l=max(1ll,i-h[i]+1);
val=f[i-1];
while(l<=s1.top()[0]){
val=min(s1.top()[1],val);
s1.pop();
}
s1.push({i,val});
s2.push(min(s2.top(),f[i-1]+c[i]));
f[i]=min(s2.top(),val+c[i]);
for(j=0;j<cnt[i];j++)s2.pop();
}
cout<<f[m];
}

Codeforces Round #541 (Div. 2) G dp + 思维 + 单调栈 or 链表 (连锁反应)的更多相关文章

  1. Codeforces Round #541 (Div. 2) E 字符串 + 思维 + 猜性质

    https://codeforces.com/contest/1131/problem/D 题意 给你n个字符串,字符串长度总和加起来不会超过1e5,定义字符串相乘为\(s*s1=s1+s[0]+s1 ...

  2. Codeforces Round #333 (Div. 1)--B. Lipshitz Sequence 单调栈

    题意:n个点, 坐标已知,其中横坐标为为1~n. 求区间[l, r] 的所有子区间内斜率最大值的和. 首先要知道,[l, r]区间内最大的斜率必然是相邻的两个点构成的. 然后问题就变成了求区间[l, ...

  3. Codeforces Round #541 (Div. 2)

    Codeforces Round #541 (Div. 2) http://codeforces.com/contest/1131 A #include<bits/stdc++.h> us ...

  4. Codeforces Round #582 (Div. 3)-G. Path Queries-并查集

    Codeforces Round #582 (Div. 3)-G. Path Queries-并查集 [Problem Description] 给你一棵树,求有多少条简单路径\((u,v)\),满足 ...

  5. Codeforces Round #346 (Div. 2) G. Fence Divercity dp

    G. Fence Divercity 题目连接: http://www.codeforces.com/contest/659/problem/G Description Long ago, Vasil ...

  6. Codeforces Round #541 (Div. 2)题解

    不知道该更些什么 随便写点东西吧 https://codeforces.com/contest/1131 ABC 太热了不写了 D 把相等的用并查集缩在一起 如果$ x<y$则从$ x$往$y$ ...

  7. Codeforces Round #547 (Div. 3) G 贪心

    https://codeforces.com/contest/1141/problem/G 题意 在一棵有n个点的树上给边染色,连在同一个点上的边颜色不能相同,除非舍弃掉这个点,问最少需要多少种颜色来 ...

  8. Codeforces Round #546 (Div. 2) D 贪心 + 思维

    https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则, ...

  9. Codeforces Round #481 (Div. 3) G. Petya's Exams

    http://codeforces.com/contest/978/problem/G 感冒是真的受不了...敲代码都没力气... 题目大意: 期末复习周,一共持续n天,有m场考试 每场考试有如下信息 ...

随机推荐

  1. 有关html5的history api

    从Ajax翻页的问题说起 请想象你正在看一个视频下面的评论,在翻到十几页的时候,你发现一个写得稍长,但非常有趣的评论.正当你想要停下滚轮细看的时候,手残按到了F5.然后,页面刷新了,评论又回到了第一页 ...

  2. GridView和DataFormatString 日期格式 精确小数点后位数

    如果DataFormatString无效,请添加属性 HtmlEncode = "false" --------------------------------------- Da ...

  3. Properties 使用

    Properties 属于Map 下HashTable的小弟 属于持久的属性集,他可以保存在流中或者在流中加载. 键和值都是字符串类型. 通常用于配置文件 方法介绍: 存放键值对:setPropert ...

  4. Character 类

    Character 类用于对单个字符进行操作. Character 类在对象中包装一个基本类型 char 的值 char ch = 'a'; // Unicode 字符表示形式char uniChar ...

  5. 关于vue搭建项目运行出行的错误问题,简直是大坑啊

    解决方法简单粗暴,非常简单粗暴 直接在根目录新建一个test文件夹就可以搞定,用来放置配置文件的 折腾了我一上午啊

  6. MySQL 中的数据类型介绍(转)

    据我统计,MySQL支持39种(按可使用的类型字段统计,即同义词也作多个)数据类型.下面的介绍可能在非常古老的mysql版本中不适用. 转载出处:http://blog.csdn.net/anxpp/ ...

  7. sqlserver数据库的分离与附加

    当我们一台电脑上创建了数据库想要转移到另外一台电脑上时,由于数据库处于联机状态,不能够对数据库文件进行复制和迁移,所以我们可以将数据库从服务器上分离出去,这样我们就可以复制数据库文件了.然后将数据库文 ...

  8. shell 脚本编写基础

    在进行Linux测试时编写脚本是必不可少的,Shell脚本的名称可以随便定义,也不要什么后缀名,例如可以写abc,smartzip这类名称,运行时只要键入 ./smartzip就能运行脚本了.. 每行 ...

  9. 在threejs中添加两个场景和相机是需要注意render的参数设置

    问题:我刚开始设置了两个场景和相机 但是第二个一直将第一个场景给覆盖了一直找不到原因 解决: 问题出在 renderer.autoClear = false;上 设置render的参数如下: rend ...

  10. python 数据类型 之 利用 dict 模仿 switch语句功能

    Python本身并不提供Switch的语法功能,为了能够解决类似switch分支需求的问题,我们可以使用字典代替实现. 解决思路: 利用字典取值的get方法的容错性,处理switch语句中的defau ...