联合省选 2024 Day2T1 迷宫守卫 题解

联合省选 2024 Day2T1 迷宫守卫 题解

好像距离联合省选已经半年了,前两天看到这题才想起来改,距离分班已经半年了,也算是好好学了半年了,但是还是那么菜,有点绷不住,感觉不如文化课

后来翻到题解区第二篇题解才知道自己赛时想的反悔贪心其实是正解,但是当时啥也不会,主要是不会实现,加上当时实现思路也有点问题,又不会分析复杂度,当时狂想写,但是狂挂不止

回到反悔贪心 :

Part 1 思路

首先,Bob会选定一个目标点,向着目标点走来获取符文,由于字典序的性质,他一定首选 \(1\) 此时只有两种情况

  1. Alice 可以通过唤醒守卫来阻止 Bob 拿到 \(1\)
  2. Bob 可以顺利拿到 \(1\)

假如说是情况 1,那么 Bob 一定不会选择 \(1\),因为 Alice 一定会把先 \(1\) 堵上,我们顺次考虑2、3、4...即可

如果说是情况二,Bob会走到 \(1\) 对应的叶子,而 Alice 不能做出任何决定,答案的第一位也就确定了

之后的子树内递归进行此操作即可

问题在于 Alice 可能会有多种方式来堵上字典序小的那些数,假如说她无脑选择当前价值最小的,可能会因为作用域太小而得到较劣的解

那么我们可以先贪心选择对当前局面有最好影响的价值和最小方案,等到该决策失效的时候再考虑将其更换

以上图为例,假如我们只有三的权值,那么根据贪心策略,会先选唤醒根节点的守卫,可是我们发现这样的答案是

2 5 3 4 1 6 7 8

但是假如我们唤醒节点 \(3\) 的守卫,答案就会变成

2 5 3 4 7 8 1 6

显然后者更优,这是因为后者深度更大,守卫的子树规模较小,但是守卫的持续时间也更长,所以一旦走入一个守卫的守护范围,我们就要反悔,考虑将它换成若干个深度较大的守卫,这符合我们先保证高位大,后尽量顺次考虑的要求,这里证明也挺容易的

Part2 代码框架

对于决定这个目标点,我们发现是单调的,直接二分就好,对于顺次跳链,dp等做法暂时不进行介绍

二分的check 可以写 \(O(n)\) 的 dp,求出答案为当前值最小的代价能否承受即可,转移啥的是显然的

我们对于二分的点,直接走到那个节点,容易发现走的链将树分割成 \(1\)\(2\)\(3\)\(4\)\(h-1\)... 的好多不同规模的子树,递归做,进去之前把之前决策对比一下撤销就完了

考虑分析复杂度,设 \(f(h)\) 是解决一棵高度为 \(h\) 的子树的复杂度,有

\[f(h)=h2^h+\sum \limits _{i=1}^{h-1} f(i) \]

给它分个组,得到

\[f(h)=h2^h+\sum \limits _{i=1}^{h-2} f(i)+f(h-1) \]

又有

\[f(h-1)=\sum \limits _{i=1}^{h-2} f(i)+(h-1)2^{h-1} \]

也就是说

\[f(h)=h2^h+2f(h-1)-(h-1)2^{h-1} \]

发现第 \(i\) 层分裂出来的复杂度是 \(O(i2^h)\),一共 \(h\) 层,所以单次复杂度为 \(O(n^22^n)\) 完全可以接受

Part3 实现

这题想明白之后实现其实不难,考虑每次从底向上跳,其实主要是捋清楚思路,想明白什么时候撤销,应该怎样撤销

赛时甚至一直试图记录下来每次贪心后选取的点,后来因为太难写,完全不敢也不会写这个做法最后写了删删了写,还是只糊了暴力

贴个代码

CODE
#include<bits/stdc++.h>
#define llt long long
const llt N=201000;
using namespace std;
llt T,n,k,w[N],Q[N],dp[N][2],sum,to[N];vector<llt> vec,ans;bool jud[N];
void solve(llt,llt);
void DP(llt now,llt pl,llt h)
{dp[now][0]=dp[now][1]=0;if(h==n)    {if(Q[now<<1|1]<pl)   dp[now][0]=w[now],dp[now][1]=0;if(Q[now<<1]<pl)    dp[now][0]=1e18,dp[now][1]=0;return;}DP(now<<1|1,pl,h+1),DP(now<<1,pl,h+1);dp[now][1]=min(dp[now<<1|1][1],dp[now<<1|1][0])+min(dp[now<<1][1],dp[now<<1][0]);dp[now][0]=min(dp[now<<1][0]+dp[now<<1|1][1]+w[now],dp[now<<1][0]+dp[now<<1|1][0]);
}
llt find(llt now,llt h)
{llt l=0,r=vec.size()-1,mid;while(l<r){mid=l+r+1>>1;DP(now,vec[mid],h);if(dp[now][0]<=k-sum)   l=mid;else r=mid-1;}DP(now,vec[l],h);sum+=dp[now][0];return vec[l];
}
void jump(llt now,llt pl,llt h,llt root)
{jud[now]=1;DP(now,pl,h);if(jud[now<<1|1]) sum-=dp[now<<1][0],solve(now<<1,h+1);else{sum-=min(dp[now<<1|1][0],w[now]);if(dp[now<<1|1][0]+sum>k)   sum+=w[now],solve(now<<1|1,h+1);else solve(now<<1|1,h+1);}if(now==root)    return;jump(now>>1,pl,h-1,root);
}
void solve(llt now,llt h)
{if(h>n) {ans.push_back(Q[now]);return;}vector<llt>().swap(vec);for(int i=(1<<n-h+1)*now,j=1;j<=(1<<n-h+1);i++,j++)vec.push_back(Q[i]);sort(vec.begin(),vec.end());llt oo=find(now,h);ans.push_back(oo);jud[to[oo]]=1;jump(to[oo]>>1,oo,n,now);
}
int main()
{#ifdef LOCALfreopen("1.in","r",stdin);freopen("1.out","w",stdout);#endifscanf("%lld",&T);while(T--){vector<llt>().swap(ans);sum=0;memset(dp,0,sizeof(dp));scanf("%lld%lld",&n,&k);for(int i=1;i<(1<<n);i++)   scanf("%lld",&w[i]);for(int i=(1<<n);i<(1<<n+1);i++)   scanf("%lld",&Q[i]),to[Q[i]]=i;solve(1,1);for(auto v:ans) printf("%lld ",v);puts("");memset(jud,0,(1<<n+1)*sizeof(bool));}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/775796.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小白程序员也要对世界进行第一次的呐喊!

身为程序员对世界的第一声呐喊——Hello World!新建一个文件夹 新建一个目录,并将其命名为Hello.java(关键一步)注意!文件类型显示的是java文件才成功 (文件的后缀要改为java)双击文件,开始编写(本人使用的是Notepad++进行编写) 输入图片中的代码(全部要用英文输入法…

Django模板、模版语言和静态文件

1. templates模板(html)在app目录下创建一个templates目录,用于存放网页模板利用url返回网页点击查看代码 def user_list(request):return render(request,"user_list.html");输入url地址时,会去app目录下的templates目录下寻找名为user_list的HTML文件(根据app…

Cuberite——低配mc服务器的最佳选择

最近白嫖了一个1h1g的服务器,想拿它来开mc服务器,正当我用mcsmanager开服的时候,突然给我报了一条OutOfMemoryError下面就给大家介绍一下Cubreite Cuberite Cuberite is a Minecraft-compatible multiplayer game server that is written in C++ and designed to be efficie…

一图看懂Git、HTTPS、Docker、k8s和微服务

一图看懂Git、HTTPS、Docker、k8s和微服务

全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用

在Python中,断言是一种常用的调试工具,它允许程序员编写一条检查某个条件。本文主要介绍了断言的应用场景和特点以及assert语句的使用,同时介绍了防御性编程和help()函数。全网最适合入门的面向对象编程教程:29 类和对象的 Python 实现-断言与防御性编程和 help 函数的使用…

《NET CLR via C#》---第四章(System.Object,类型转换,is和as,命名空间和程序集,运行时的相互关系)

System.Object CLR要求每个类型最终都从System.Object类型派生。由于所有类型最终都从System.Object派生,所以每个类型的每个对象都保证了一组最基本的方法。公共方法 说明Equals 如果两个对象具有相同的值,就返回trueGetHashCode 返回对象的值的哈希码。如果某个类型的对象要…

笔记:从Aurora 8b/10b 到Aurora 64b/66b (一):64b/66b 基本知识

参考搬运: https://mp.weixin.qq.com/s/ZSNyjpZpimjyxyO9riIRNQ Aurora 64B/66B (xilinx.com) https://docs.amd.com/r/en-US/pg074-aurora-64b66b 8/10:SATA SRIO 64/66:10G以太网 值得注意: 64b/66b 编码在多LANE模式下,EOF(T)仅在一个LANE上出现; 介绍 8B10B的开销比较…

matlab中用plotyy画双纵轴图

clear clcx1 = 1:0.1:6; x2 = 2:0.1:7; y1 = sin(x1); y2 = 0.5*x2; y3 = sin(x1)+x1; y4 = cos(x2)+x2;figure; [hAx,hLine1,hLine2] = plotyy([x1, x2],[y1, y2], [x1, x2],[y3, y4]); hold on; set(hAx(1), YColor, r); % 设置第一条y轴的颜色为红色 set(hAx(2), YColor, b)…

【专题】2023年中国数字金融调查报告PDF合集分享(附原数据表)

原文链接:https://tecdat.cn/?p=34685 原文出处:拓端数据部落公众号 随着数字化转型的深入推进,新客户的增长速度已达顶峰,用户运营成为推动存量增长的关键手段。调查数据显示,相比去年,网上银行用户比例有所下降,而手机银行用户比例基本持平。阅读原文,获取专题报告合…

在r语言中使用GAM(广义相加模型)进行电力负荷时间序列分析

原文链接:http://tecdat.cn/?p=9024 原文出处:拓端数据部落公众号最近我们被要求撰写关于GAM的研究报告,包括一些图形和统计输出。 用GAM进行建模时间序列 我已经准备了一个文件,其中包含四个用电时间序列来进行分析。数据操作将由data.table程序包完成。 将提及的智能电表…

饮冰十年-人工智能-Vue3-67-组件间数据交互

上一篇:饮冰三年-人工智能-Vue-66 Vue组件化很久以前我对Vue2的组件间数据交互做过学习,兜兜转转再用Vue已经是Vue3版本。 Vue3组件间数据交互 1、准备工作环境准备使用 Vite 创建一个新的 Vue 3 项目功能介绍该功能由APPVue+4个组件组成 头部组件(MyHeader) 主…