约瑟夫环加强版用线段树解决m,,这类问题还可以拓展,只是一个思路,用线段树的思路要学习
2011-02-06 14:22
393 查看
这一类题还有一个重点就是
数据结构 倒序考虑会存在某种关系的思虑 十分重要
铭记这种思路
题意:
n个人每个人有一个id还有一个numI ,开始从第k个人开始,第k个被拿出去,然后下一个被拿出去的是从第k个人往下数numI个,如果numI是正数那么就顺时针数numI个,如果是负数,就逆时针数abs(numI)个。第i个被拿出的人,得的分数,为i的因子个数。问谁的分数最高.
解答:
首先求最大分数是求反素数问题
先看什么是反素数
对于任何正整数x,起约数的个数记做g(x).例如g(1)=1,g(6)=4.
如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数.
现在给一个N,求出不超过N的最大的反素数.
然后求第I个人是谁
如果模拟是 n^2的时间复杂度。但是用线段数做可以降低到 nlogn
已知当前轮的所有人的新编号,怎么知道下一个被拿走的人的编号呢?
看约瑟夫环问题怎么进行更新
现在n中第k个人被杀死,他逆时针的第m个人(下个被杀死的),那个人在剩余的n-1个人中是第((k-m2-1)%(n-1)+(n-1))%(n-1)+1个,他顺时针第m2个人(下一个被杀死)在那个人是剩余的n-1个人中是第((k+m2-2)%(n-1)+(n-1))%(n-1)+1
(规则人从1到n编号,被杀死后,依然是按照原来的顺序从1到n-1编号)
先看线段数结构
struct tnode
{
int l,r,sum;
int mid(){return (l+r)/2;}
}
sum是这一段上还剩多少人。
所以在查找的时候我们相当于是二分查找剩下的第 i 个人是原来最开始的第 几号。并且更新把这个人剔除后的sum值。
见下面
int find(int nod,int m)
{
tree[nod].sum--;
if(tree[nod].l==tree[nod].r)
return tree[nod].l;
if(tree[L(nod)].sum>=m)
return find( L(nod),m );
if(tree[L(nod)].sum<m)
return find(R(nod),m-tree[L(nod)].sum);
}
这样就可以找到 这一轮谁被剔除。
这个方法很巧妙。
poj 2828也是这一类问题的拓展
题意
N 个人排队,
4 (4个人排队)
0 77
1 51
1 33
2 69 表示 名字叫77那个人插到第0位,名字为51那个人插到第1位,名字为33那个人插到第1位,名字为69那个人插到第2位,最后排队序列77 33 69 51。求这个最后排队序列。
主要是考虑倒序关系,然后用线段树预留位置。预留位置线段树操作跟约瑟夫十分类似
数据结构 倒序考虑会存在某种关系的思虑 十分重要
铭记这种思路
题意:
n个人每个人有一个id还有一个numI ,开始从第k个人开始,第k个被拿出去,然后下一个被拿出去的是从第k个人往下数numI个,如果numI是正数那么就顺时针数numI个,如果是负数,就逆时针数abs(numI)个。第i个被拿出的人,得的分数,为i的因子个数。问谁的分数最高.
解答:
首先求最大分数是求反素数问题
先看什么是反素数
对于任何正整数x,起约数的个数记做g(x).例如g(1)=1,g(6)=4.
如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数.
现在给一个N,求出不超过N的最大的反素数.
然后求第I个人是谁
如果模拟是 n^2的时间复杂度。但是用线段数做可以降低到 nlogn
已知当前轮的所有人的新编号,怎么知道下一个被拿走的人的编号呢?
看约瑟夫环问题怎么进行更新
现在n中第k个人被杀死,他逆时针的第m个人(下个被杀死的),那个人在剩余的n-1个人中是第((k-m2-1)%(n-1)+(n-1))%(n-1)+1个,他顺时针第m2个人(下一个被杀死)在那个人是剩余的n-1个人中是第((k+m2-2)%(n-1)+(n-1))%(n-1)+1
(规则人从1到n编号,被杀死后,依然是按照原来的顺序从1到n-1编号)
先看线段数结构
struct tnode
{
int l,r,sum;
int mid(){return (l+r)/2;}
}
sum是这一段上还剩多少人。
所以在查找的时候我们相当于是二分查找剩下的第 i 个人是原来最开始的第 几号。并且更新把这个人剔除后的sum值。
见下面
int find(int nod,int m)
{
tree[nod].sum--;
if(tree[nod].l==tree[nod].r)
return tree[nod].l;
if(tree[L(nod)].sum>=m)
return find( L(nod),m );
if(tree[L(nod)].sum<m)
return find(R(nod),m-tree[L(nod)].sum);
}
这样就可以找到 这一轮谁被剔除。
这个方法很巧妙。
poj 2828也是这一类问题的拓展
题意
N 个人排队,
4 (4个人排队)
0 77
1 51
1 33
2 69 表示 名字叫77那个人插到第0位,名字为51那个人插到第1位,名字为33那个人插到第1位,名字为69那个人插到第2位,最后排队序列77 33 69 51。求这个最后排队序列。
主要是考虑倒序关系,然后用线段树预留位置。预留位置线段树操作跟约瑟夫十分类似
相关文章推荐
- 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决
- 想做一个可以赚钱的网站需要解决哪些问题
- hibernate3.0发现在海量数据表中查询很慢 ,不在于问题,在于解决问题的思路啊,学习了
- 学习解决问题的思路
- Mac OS X: MS Office for Mac问题解决的一个思路
- 用Unity3D想做一个简单的赛车游戏,现在的问题是转弯的时候很容易出现翻车的情况,求解决思路
- 根据自身工作经验总结的一个工作问题解决思路
- 解决一个问题的思路 之“解决已经写满con.close() 仍然出现"但是尚未从池中获取连接"的连接池耗尽问题”
- [学习记录]关于解决问题思路的一些反思
- 这是我学习COM遇到的几个基本问题其解决 黄森堂(vcmfc)著 1.我用ATL生成一个组件对象,我在COM中使用IDD_IEncrypt,这个在哪里写义,是啥?GUID? 答:IDD_IEncry
- 一个发邮件的类,带验证功能,可以发html内容,可以添加附件,并解决附件乱码问题。
- "Visual studio .net 无法创建或打开应用程序" 问题的一个解决思路
- 解决学习tensorflow的LSTM模型中遇到一个版本不兼容问题
- SQLSERVER解决HOT PAGE问题的其中一个思路使用表分区
- java数据结构与算法分析学习(编写一个程序解决选择问题,k=N/2)
- 一个Android多平台问题兼容解决思路
- boj problem 1331 思路:快排分块 按块查找 问题:全局数组时可以定义到500W的 main函数下的数组不行~ 另外c语言比c++快 TLE可以考虑C~~具体原因待解决
- 一个框架解决几乎所有机器学习问题
- 通过一个小技巧可以让flash和iframe的在ie下遮挡问题解决
- 用NSIS安装日志install。log解决了一个安装出现隐蔽的问题、不用看代码,可以节省大把时间!开心!