2021-09-07 test

  • [TJOI2013]拯救小矮人
  • 「ICPC World Finals 2019」Hobson 的火车

[TJOI2013]拯救小矮人

luogu4823

考试题目的数据加强为2e5,所以此题做法应为O(nlog⁡n)O(n\log n)O(nlogn)的反悔贪心

这种有多元属性,选择最优的问题

如果发现简单的贪心总是半错半对的

解法通常有两种

  • 设计dp进行转移
  • 考虑反悔贪心

此题也不意外

定义每个人所需的逃出高度为H−ai−biH-a_i-b_iH−ai​−bi​

observation1 : 逃出高度越高的人越先逃出

当然可能某些人的属性是极端的,比如身高非常高而手很短,却被派到前面,这个时候可能不让此人逃走能让后面的人走得更多,才是最佳方案

从这种情况上得出

observation2 : 如果断定此人不逃出,那么就永远不会再给机会逃出

observation3 : 如果此人不能逃出,但是前面逃出的人有高度更高的,就把最高的那个人扔回来,换成这个人逃出

到这里就可以使用优先队列维护做了

接下来给出性质一和性质三的证明

  • 性质一:

    考虑先逃走的人逃出高度为h1h_1h1​,再逃走的逃出高度为h2h_2h2​

    则有h1>h2h_1>h_2h1​>h2​,即H−a1−b1>H−a2−b2⇒a1+b1<a2+b2H-a_1-b_1>H-a_2-b_2\Rightarrow a_1+b_1<a_2+b_2H−a1​−b1​>H−a2​−b2​⇒a1​+b1​<a2​+b2​

    设hhh为还在洞内所有人的身高包含1,2

    如果1,2都能逃出,那么1,2之间逃出的顺序,对后面的人不会影响,反正都不会有身高的贡献

    也就是说,我们需要证明当满足h1>h2h_1>h_2h1​>h2​条件时,1更难逃出,所以需要先走

    既然2能逃走,说明不需要1的身高,即h−a1+a2+b2≥Hh-a_1+a_2+b_2\ge Hh−a1​+a2​+b2​≥H

    如果2先逃走,1也能逃走,则必须满足h−a2+a1+b1≥Hh-a_2+a_1+b_1\ge Hh−a2​+a1​+b1​≥H

    • −a1+a2+b2?−a2+a1+b1⇔a2+a2+b2?a1+a1+b1-a_1+a_2+b_2\quad?\quad -a_2+a_1+b_1\Leftrightarrow a_2+a_2+b_2\quad ?\quad a_1+a_1+b_1−a1​+a2​+b2​?−a2​+a1​+b1​⇔a2​+a2​+b2​?a1​+a1​+b1​

      a1+b1<a2+b2⇒a1<a2+b2−b1a_1+b_1<a_2+b_2\Rightarrow a_1<a_2+b_2-b_1a1​+b1​<a2​+b2​⇒a1​<a2​+b2​−b1​

      a1+a1+b1<a2+b2−b1+a1+b1=a2+b2+a1a_1+a_1+b_1<a_2+b_2-b_1+a_1+b_1=a_2+b_2+a_1a1​+a1​+b1​<a2​+b2​−b1​+a1​+b1​=a2​+b2​+a1​

    所以?应为>

    也就是说2逃出时超出HHH的距离更多,也就是比1逃出条件要松一点

    如果1逃走后2无法出逃,那么2逃走后1更无法逃出,且加紧了后面的约束

    当然这只是充分证明,因为会考虑逃不走换人的情况,结合反悔贪心才是最后的贪心

  • 性质三:

    对于某个不能逃出的人,选择前面比自己高的最高的人,换进来

    这反悔贪心很显然,换一个人进来换一个人出去,对人数没有影响

    但是换了个更高的人进来,那么其高度就会松弛后面所有人的逃出条件,使得逃出可能性增大

    • 接下来证明,在逃出条件越后越松弛的前提下,换一个更高的人进来,自己一定可以逃出去

      假设2此时无法逃出,需要把前面的1换进来,定义hhh为在洞内的人的高度加上已经逃出的1的高度

      则a1+b1<a2+b2a_1+b_1<a_2+b_2a1​+b1​<a2​+b2​ 且 a1>a2a_1>a_2a1​>a2​

      把在1,2之间逃出洞的所有人先再次丢回洞中,相当于回溯到第一次决定让1逃出的时刻

      因为逃出高度限制是逐渐宽松的,既然这个时候1能逃出,2一定也能逃出

      考虑变成2逃出对之前在1,2中间逃出的人的影响,发现是正面影响

      因为2的高度没有1高,相当于换了一个更高的人垫背,那么原来在1,2中间逃出的人同样也会逃离

#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
#define maxn 200005
priority_queue < int > q;
struct node { int a, b, h; }p[maxn];
int n, H;
int h[maxn];signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ )scanf( "%lld %lld", &p[i].a, &p[i].b );scanf( "%lld", &H );for( int i = n;i;i -- )p[i].h = H - p[i].a - p[i].b;sort( p + 1, p + n + 1, []( node x, node y ) { return x.h > y.h; } );for( int i = n;i;i -- )h[i] = h[i + 1] + p[i].a;int now = 0, ans = 0;for( int i = 1;i <= n;i ++ )  if( now + h[i + 1] >= p[i].h ) ans ++, q.push( p[i].a );else {if( ! q.empty() and q.top() > p[i].a )now += q.top(), q.pop(), q.push( p[i].a );elsenow += p[i].a;}printf( "%lld\n", ans );return 0;
}

「ICPC World Finals 2019」Hobson 的火车

LOJ6548

恰好考了一下最近学的基环树

如果是问从每个点开始能访问的点数,那么就非常简单,是个外环树

每个非环树上的点的路径都是一条链,只需要考虑深度和kkk的关系即可

但不巧的是这道题是求每个点可以被多少个点访问到,是个内环树

发现时间卡在设计DPDPDP的kkk转移上

很妙的,又是前几天考试的解法就是——树上差分和环上差分

具体细节实现可看代码及注释

#include <cstdio>
#include <vector>
using namespace std;
#define maxn 500005
vector < int > G[maxn], circle;
int n, k, siz, top;
int ans[maxn], dep[maxn], vis[maxn], s[maxn], d[maxn];void dfs( int u, int rt ) {if( ! vis[u] ) vis[u] = 1; //在求该联通分量时可能有些点还未访问过 身处环遍历后面 s[++ top] = u;if( top > k + 1 and s[top - k - 1] ^ circle[rt] )    //差分 与u点相距k+1甚至更远的点不再有贡献 ans[s[top - k - 1]] --;for( auto v : G[u] )if( vis[v] == 2 ) continue;//环点在后面单独更新else { dep[v] = dep[u] + 1;dfs( v, rt );if( u ^ circle[rt] ) ans[u] += ans[v];}top --;if( dep[u] <= k ) { //会延伸到部分环点 哪怕只有一个点 //环长虽然是siz 但实际上只需要走siz-1步就会遍历完所有环点 if( dep[u] + siz > k + 1 ) { //无法在k步内将环都覆盖完 int t = ( rt + k - dep[u] + 1 ) % siz;/*rt+k-dep[u]是真正差分的结束位置需要在结束位置的下一位pos+1打上-1抵消标记 */ans[circle[rt]] ++, ans[circle[t]] --;if( t < rt ) ans[circle[0]] ++;/*由于环差分也是从环头遍历到环尾 默认断开了环头与环尾的边 该if成立说明覆盖的部分点跨越了环尾在环头多延伸了一点 环头到结束位置也应该差分*/ }else ++ ans[circle[0]]; //该点可以访问所有环点 直接在环头++ }if( u ^ circle[rt] ) ans[u] ++;
}void dfs( int now ) {circle.clear();while( vis[now] ^ 2 ) { //如果now点先前已经被遍历2次 也就是回到了环头 不再重复入环 if( vis[now] ) circle.push_back( now ); //再次经过now点说明是环上一点 开始进入求环部分 vis[now] ++;now = d[now];}siz = circle.size();for( int i = 0;i < siz;i ++ )//先差分求每个环点的非环树答案 dfs( circle[i], i );for( int i = 1;i < siz;i ++ )//环差分 ans[circle[i]] += ans[circle[i - 1]];
}int main() {scanf( "%d %d", &n, &k );for( int i = 1;i <= n;i ++ ) {scanf( "%d", &d[i] );G[d[i]].push_back( i );//建反图 }for( int i = 1;i <= n;i ++ )if( ! vis[i] ) dfs( i );for( int i = 1;i <= n;i ++ )printf( "%d\n", ans[i] );return 0;
}

[TJOI2013]拯救小矮人(反悔贪心证明),「ICPC World Finals 2019」Hobson 的火车(基环树,差分)相关推荐

  1. 【bzoj3174】[Tjoi2013]拯救小矮人 贪心+dp

    题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...

  2. 洛谷 P4823 [TJOI2013]拯救小矮人

    题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口. 对于每一个小矮人,我们知道他从 ...

  3. 浅析拯救小矮人的 nlogn 算法及其证明

    浅析拯救小矮人的 nlogn 算法及其证明 题型简介: 有 $ n $ 个人,第 $ i $ 个人身高 $ a_i $ 手长 $ b_i $ ,他们为了从一个高为 $ H $ 的洞中出去,决定搭人梯. ...

  4. 【BZOJ3174】【codevs25442075】拯救小矮人,DP+贪心

    Time:2016.07.19 Author:xiaoyimi 转载注明出处谢谢 传送门1 传送门2 传送门3 思路: 比较神的DP "贪心确定DP的状态"--reflash 写了 ...

  5. 使用canvas实现小矮人行走案例

    html代码 <canvas width="500" height="500"></canvas> <script src=&qu ...

  6. 项目管理小故事之小矮人的故事

    小矮人的故事 在古希腊时期的塞浦路斯,曾经有一座城堡里关着一群小矮人.传说他们是因为受到了可怕咒语的诅咒,而被关到这个与世隔绝的地方.他们找不到任何人可以求助,没有粮食,没有水,七个小矮人越来越绝 望 ...

  7. 《讲个故事》七个小矮人 与 七层模型

    某天深夜,标准委员会的工程师们的在酒吧里喝酒划拳,酒过三巡,越玩越嗨,谈到迪士尼电影的时候,他们把电影里7个小矮人的名字写在餐巾纸上,有个人开玩笑说 7 对于网络分层是个好数字.第二天上午在标准化委员 ...

  8. 《讲个故事》七个小矮人与OSI七层模型

    某天深夜,标准委员会的工程师们的在酒吧里喝酒划拳,酒过三巡,越玩越嗨,谈到迪士尼电影的时候,他们把电影里7个小矮人的名字写在餐巾纸上,有个人开玩笑说 7 对于网络分层是个好数字.第二天上午在标准化委员 ...

  9. [codevs 1302] 小矮人(2002年CEOI中欧信息学奥赛)

    描述 矮人们平时有走亲访友的习惯.一天,矮人国要修一条高速公路,矮人们希望他们走亲访友的时候,能够不必穿越高速公路,这样会更安全一些.现在有M个高速公路的修建方案,请你判断这M条高速功能是否能满足矮人 ...

最新文章

  1. Java使用itext生成Pdf
  2. leetcode208. 实现 Trie (前缀树)
  3. 利用layui来完成垂直和侧边导航的小案例
  4. 调车遇到的问题及解决办法
  5. 随想录(虚拟机实现)
  6. 只在用户登陆时运行_linux 系统的7个运行级别
  7. MySQL语法一:数据定义语句
  8. 计算机系统基础lab2(二进制炸弹实验)
  9. TCP通讯中发送文件
  10. 什么是python web
  11. 有什么变音视频软件?这些软件值得收藏
  12. 我推荐这几个好玩有趣的小网站
  13. 计算机中保存和另存为,电脑另存为在哪里
  14. 把代码字体加大的办法
  15. java西历转换和历_java西历转换和历
  16. JQuery序列化和反序列化
  17. element-UI中使用树组件el-tree实现左侧勾选右侧列表展示并且列表删除某一项左侧树菜单取消相应勾选
  18. 使用Pytorch实现简单的LSTM股票预测框架
  19. CPU比GPU训练神经网络快十几倍,英特尔:别用矩阵运算了
  20. S1000D 5.0 中文版

热门文章

  1. jquery如何实现ajax技术,使用JavaScript和jQuery简单实现Ajax技术(示例代码)
  2. hadoop 2.7 java_Hadoop2.7环境搭建---Java环境变量
  3. imac android studio,Mac安装Android Studio的时候忘记安装Avd Manager怎么办?
  4. php curl hostname,php – 如何解决cURL错误(7):无法连接到主机?
  5. 简单计算机面试题库及答案_计算机专业复试面试问题含答案
  6. mysql 用户概念_传输概念 – db对象的用户/组/权限从mysql到postgresql
  7. java jdbc分页_使用JDBC进行分页查询
  8. mongodb默认的用户名密码_设置mongodb的用户名密码 | Think in Drupal
  9. mui 时间样式错乱_微信编辑器样式排版错位怎么回事?
  10. m苹果放n篮子_egg appple千万别翻译为“鸡蛋苹果”,老外听到会懵圈的