洛谷 P11411 兰奇的卡牌游戏——题解

news/2024/12/21 22:22:51/文章来源:https://www.cnblogs.com/qc0817/p/18621480

洛谷P11411兰奇的卡牌游戏


传送锚点


摸鱼环节

兰奇的卡牌游戏

题目描述

作为制卡大师的兰奇,发明了一种自助型卡牌游戏。

给定 \(n\) 张卡牌,第 \(i\) 张卡牌编号为 \(i\),其权值为 \(a_i\),卡牌的权值互不相同。

这个卡牌游戏的规则需要自己生成。一开始,所有的牌都在备选区。从备选区中选取一张编号最小的卡牌放到手牌区,便可进入规则生成阶段。

规则生成阶段的步骤如下:

  1. 将手牌区的任意一张牌弃置到废牌区之中。

  2. 然后在备选区中选择一张编号和权值均大于当前弃牌的牌,加入手牌区。若存在这样的一张牌,则称这张牌与弃牌互为置换;若不存在这样的一张牌,则跳过当前步骤。

  3. 继续从备选区中选择一张编号大于当前弃牌且权值小于当前弃牌的牌,加入手牌区。若存在这样的一张牌,则同样可称这张牌与弃牌互为置换;若不存在这样的一张牌,则跳过当前步骤。

  4. 完成以上步骤后,若手牌区没有卡牌了,则规则生成阶段结束。若仍有卡牌,则继续重复上述步骤,直到手牌区没有卡牌。

为了保证生成置换的唯一性,兰奇规定规则生成阶段合法当且仅当规则生成结束后,所有的牌都在废牌区。并且在正式游戏阶段一张编号较大的牌经过一系列操作后得到一张编号较小的牌后,该编号较大的牌,均要满足能够有机会按照在手牌区出现过的该张编号较小的牌的弃牌后生成的置换相同的步骤在规则生成阶段成为编号较小的牌的置换;若手牌区未出现该张编号较小的牌的弃牌后生成的置换,则无需考虑。否则,生成的置换是无效的。

可以证明在规则生成阶段合法的情况下,每张卡牌可以与哪些卡牌互为置换的方案是唯一的。

正式游戏阶段的步骤如下:

  1. 选择任意一张卡牌作为起始卡牌并加入手牌区,然后进入下一步骤。

  2. 将前手牌区的卡牌弃入废牌堆,然后从备选区中选择一张该卡牌的置换加入手牌区。若当前弃置的卡牌在备选区没有置换,则正式游戏阶段结束;反之,则得分增加 \(1\) 分,然后继续重复步骤 2。

游戏发售后,销量并不是很好。因为游戏规则太复杂了。玩家们希望删去一些卡牌,使得正式游戏阶段的最大得分不超过 \(k\)

而兰奇为了保证游戏的不做太大的改动,他要求删去一些卡牌后,保留下来的任意一张卡牌重新生成的置换要与原来未删去卡牌情况下的置换相同。

删去后置换仍相同的定义是:设 \(S\) 表示某一张卡牌,未删除任何一张卡牌时的置换集合;\(T\) 表示该张卡牌,在删除了部分卡牌时的置换集合。此时,满足 \(T \subseteq S\)。则称删去部分卡牌后,该卡牌的置换与原来未删去卡牌情况下的置换相同。

兰奇想知道,在满足了玩家和自己的要求的前提下,他最少要删除几张卡片。

输入格式

第一行输入两个正整数 \(n\)\(k\),分别表示卡牌的数量和正式游戏阶段的最大得分不能超过的值。

第二行输入 \(n\) 个元素,第 \(i\) 个元素 \(a_i\),表示编号为 \(i\) 的卡牌权值。

输出格式

输出一个正整数,表示在满足玩家和自己的要求的前提下,最少要删除几张卡片。

样例 #1

样例输入 #1

3 2
1 2 3

样例输出 #1

0

样例 #2

样例输入 #2

6 2
3 2 7 99 10 15

样例输出 #2

3

提示

【样例1解释】

编号为 \(1\) 的卡牌与编号为 \(2\) 的卡牌互为置换,编号为 \(2\) 的卡牌与编号为 \(3\) 的卡牌互为置换。

所以,在不删去的情况下,获得最大得分的方案是:用编号为 \(1\) 的卡牌作为起始卡牌置换出编号为 \(2\) 的卡牌,然后再置换出编号为 \(3\) 的卡牌。该方案的最大得分为 \(2\),所以不需要删除任何一张卡牌。

【数据范围】

本题采用捆绑测试

  • Subtask 1(15 points):\(n \le 10\)
  • Subtask 2(5 points):\(k = n\)
  • Subtask 3(80 points):无特殊限制。

对于所有测试数据,\(1 \le n \le 2000\)\(1 \le a_i \le 10^9\)


大型阅读理解,OI已经卷到考语文了?
我们需要冷静得阅(da)读(kai)题面(jie),然后惊奇的发现居然没有题解(毕竟只有暂时8个人AC)。


正片开始

Reading部分(最难的一步)

经过通读题面,我们可以很轻(jian)松(nan)地发现弃牌和选牌的过程可以构建成一棵树,然后按照规则来就可以再一次很轻松(bushi)地发现这是一棵名为笛卡尔树的树。(不会笛卡尔树可参考这篇)。

接着阅读下文就可以发现,这是在一棵笛卡尔树上删点,要求树上任意两点的距离不超过\(\frac{k}{2}\),求所删的点的最小数目。

Thinking部分

显然笛卡尔树肯定是要建的,接下来要处理两点间的距离关系,偷瞄一眼数据量,发现\(1 \le n \le 2000\)显然支持\(O(n^{2})\)的算法。这样我们就可暴力枚举点对进行删除操作,至于两点间的距离显然可以用\(LCA\)处理,然后就\(AC\)了。

Just Do It部分

  1. 首先需要建出美丽的笛卡尔树
void build()
{stack<int>s;//用单调栈O(n)实现for(int i=1;i<=n;i++){while(!s.empty()&&frz[s.top()].b>frz[i].b){l_son[i]=s.top();s.pop();}if(!s.empty())r_son[s.top()]=i;s.push(i);}while(!s.empty())//压在最底下的rt就是根节点{rt=s.top();s.pop();}
}
  1. 为了简洁明了,转存邻接表。(脑子不够用)
void rebuild()//重建
{for(int i=1;i<=n;i++){if(l_son[i]){g[i].push_back(l_son[i]);g[l_son[i]].push_back(i);}if(r_son[i]){g[i].push_back(r_son[i]);g[r_son[i]].push_back(i);}}
}
  1. \(LAC\)(为了美观可以将求\(path\)长度打包成函数)
void dfs(int u,int fa)//dep深度数组处理
{dep[u]=dep[fa]+1;f[u][0]=fa;for(auto v:g[u])if(v!=fa) dfs(v,u);
}
void bz()//倍增信息处理
{dfs(rt,0);for(int j=1;j<20;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
}
int LCA(int x,int y)//求LCA
{if(dep[x]<dep[y])swap(x,y);//dep[x]>=dep[y],跳yint dis=dep[x]-dep[y];for(int i=0;i<11;i++)if(dis>>i&1) x=f[x][i];if(x==y) return x;for(int i=10;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
int path(int x,int y)//两点间的距离
{return max(0*1ll,dep[x]+dep[y]-2*dep[LCA(x,y)]);
}
  1. 分讨\(k\)的奇偶性(\(k\)为奇数时需考虑相邻点)
if(k%2==0)
{int sd=k/2;for(int i=1;i<=n;i++){int cnt=0;for(int j=1;j<=n;j++){int ad=path(i,j);cnt+=(ad>sd?1:0);}ans=min(ans,cnt);}write(ans);
}
else
{int sd=k/2;for(int i=1;i<=n;i++){for(auto v:g[i]){int cnt=0;for(int j=1;j<=n;j++){int ad=path(i,j),ad2=path(v,j);cnt+=(ad>sd&&ad2>sd?1:0);}ans=min(ans,cnt);}}write(ans);
}
  1. 细节方面:

    1. 笛卡尔树需要以权值为第一关键字(权值可大可小),编号单调为第二关键字。
    2. 如果一不小心TLE可以尝试快读快写。

完整代码

#ifdef ONLINE_JUDGE
#else
#define Qiu_Cheng
#endif
#include <bits/stdc++.h>
#define int long long 
using namespace std;
// typedef long long ll;
const int N=1e7+50,M=1e5+5,mod=1e9+7;
inline int read()
{int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}return x*f;
}
inline void write(int x)
{if(x<0){putchar('-');x=-x;}if(x>9) write(x/10);putchar(x%10+'0');
}
const double pi=acos(-1);
int n,k,rt;
struct node
{int a,b;//编号,权值
}frz[N];
bool cmp(node a,node b){return a.a<b.a;}
int r_son[N],l_son[N];
void build()
{stack<int>s;for(int i=1;i<=n;i++){while(!s.empty()&&frz[s.top()].b>frz[i].b){l_son[i]=s.top();s.pop();}if(!s.empty())r_son[s.top()]=i;s.push(i);}while(!s.empty()){rt=s.top();s.pop();}
}
vector<int>g[N];
void rebuild()
{for(int i=1;i<=n;i++){if(l_son[i]){g[i].push_back(l_son[i]);g[l_son[i]].push_back(i);}if(r_son[i]){g[i].push_back(r_son[i]);g[r_son[i]].push_back(i);}}
}
int f[2005][32];//倍增信息
int dep[N];//点深度
void dfs(int u,int fa)
{dep[u]=dep[fa]+1;f[u][0]=fa;for(auto v:g[u])if(v!=fa) dfs(v,u);
}
void bz()
{dfs(rt,0);for(int j=1;j<20;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
}
int LCA(int x,int y)
{if(dep[x]<dep[y])swap(x,y);//dep[x]>=dep[y],跳yint dis=dep[x]-dep[y];for(int i=0;i<11;i++)if(dis>>i&1) x=f[x][i];if(x==y) return x;for(int i=10;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
int path(int x,int y)
{return max(0*1ll,dep[x]+dep[y]-2*dep[LCA(x,y)]);
}
inline void solve()
{   n=read();k=read();for(int i=1;i<=n;i++) frz[i].a=read(),frz[i].b=i;sort(frz+1,frz+n+1,cmp);build();rebuild();bz();int ans=1e9+7;if(k%2==0){int sd=k/2;for(int i=1;i<=n;i++){int cnt=0;for(int j=1;j<=n;j++){int ad=path(i,j);cnt+=(ad>sd?1:0);}ans=min(ans,cnt);}write(ans);}else{int sd=k/2;for(int i=1;i<=n;i++){for(auto v:g[i]){int cnt=0;for(int j=1;j<=n;j++){int ad=path(i,j),ad2=path(v,j);cnt+=(ad>sd&&ad2>sd?1:0);}ans=min(ans,cnt);}}write(ans);}
}
signed main()
{
#ifdef Qiu_Chengfreopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endifios::sync_with_stdio(false);cin.tie(0);cout.tie(0);// int Tt;// cin>>Tt;// while(Tt--)solve();solve();return 0;
}//  6666   66666    666666
// 6    6  6    6       6
// 6    6  6666       6
// 6    6  6   6    6
//  6666   6    6  6666666//g++ -O2 -std=c++14 -Wall "-Wl,--stack= 536870912 " cao.cpp -o cao.exe

完结收工!!!!!

个人主页

看完点赞,养成习惯

\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)

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

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

相关文章

centos上redis的安装

官网教程 redis安装官网 https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/ 可以右下方看到安装到各个平台的连接 这里我安装的是centos系统,所以选择 install Redis on Linux centos系统选择red hat安装方式下方第一条命令需要输入【y】进行确认 s…

CHM助手 高效制作接口文档

1 CHM助手 >> 高效制作接口文档 1.1 概述用户如果书写代码的过程中使用了良好的注释,比如:doxygen规范, 则有可能生成比较规范的接口文档。很多工具软件都支持编程扩展,比如:宏/脚本接口,那么,完善的接口文档将会给用户带来极大的便利,否则,软件的使用和推广都会…

CHM文件搜索显示为乱码或结果不全问题处理方法

1 生成CHM文件后搜索显示为乱码或搜索结果不全的原因及解决办法 1.1 问题背景使用一些CHM帮助制作工具生成的帮助文件,在html编辑阶段都显示正常,但是生成chm后,可能会出现以下问题:页面显示为乱码 搜索时,搜索结果为乱码 搜索不到结果,但明明打开手册时可以看到相关文字…

CHM助手 使用说明 步骤2:图片宽度转换相对宽度

1 CHM助手使用说明 >> 步骤2:图片宽度转换相对宽度 1.1 概述在文档写作界,流传一句“字不如表、表不如图”的定律,所以,即使是chm联机帮助,良好的图文排版,会让手册的知识传播效果加倍,但不幸的是,微软对chm文档的更新已经停止好多年了, 随着硬件的发展,近些年…

CHM助手 使用说明 步骤3:文字编码转换

1 CHM助手使用说明 >> 步骤3:文字编码转换 1.1 概述很多新手在制作chm帮助文档时,会发现要么搜索不全,搜索结果为乱码,要么帮助页面显示主乱码,这种情况主要是因为html文档中包含了中文,或其他语言文字,对于包含中文的chm文档,所有的html页面都必须要使用GB2312编…

CHM助手 使用说明 步骤1:清理HTML文档

1 CHM助手使用说明 >> 步骤1:清理HTML文档 1.1 应用场景由于编译CHM文档时,html文档的目标文本编码方式是GB2312,而使用第三方工具编写的html文件可能是utf8编码或者其他编码方式,有些特殊字符如:©、🕮等,在GB2312文档中显示为乱码,需要使用html符号描述方…

深度学习(超分辨率)

简单训练了一个模型,可以实现超分辨率效果。模型在这里。 模型用了一些卷积层,最后接一个PixelShuffle算子。 训练数据是原始图像resize后的亮度通道。 标签是原始图像的亮度通道。 损失函数设为MSE。 代码如下:import torch import torch.nn as nn import torch.optim as o…

k8s阶段09 Velero备份恢复功能, 云原生的定义, k8s实践项目(Mall-MicroService)

4 基于Velero的备份和恢复Velero介绍Velero是用于备份和恢复 Kubernetes 集群资源和PV的开源项目,由VMWare-Tanzu维护◼ 基于Velero CRD创建备份(Backup)和恢复作业(Restore)◼ 可以备份或恢复集群中的所有对象,也可以按类型、名称空间或标签过滤对象◼ 可基于文件系统…

AI火灾监测报警摄像机

AI火灾监测报警摄像机,作为一种结合人工智能技术和摄像监控技术的创新产品,在火灾防控领域发挥着越来越重要的作用。这种摄像机通过先进的AI算法,能够实时监测摄像头画面,识别出火灾的特征,如火光、浓烟等。一旦检测到火灾迹象,系统会立即启动报警机制,并向相关管理人员…

AI人员入侵识别摄像机

AI人员入侵识别摄像机是一种智能监控设备,利用人工智能技术辨认并报警可能的入侵行为。这种摄像机利用深度学习算法实时分析监控画面,识别出普通行人和潜在入侵者之间的差异,从而更准确地预警可能发生的安全事件。AI人员入侵识别摄像机是一种智能监控设备,利用人工智能技术…