wikioi-天梯-进入省队-线段树-1282:约瑟夫问题
来源:互联网 发布:淘宝云标签考试 编辑:程序博客网 时间:2024/05/16 01:20
题目描述 Description
有编号从1到N的N个小朋友在玩一种出圈的游戏。开始时N个小朋友围成一圈,编号为I+1的小朋友站在编号为I小朋友左边。编号为1的小朋友站在编号为N的小朋友左边。首先编号为1的小朋友开始报数,接着站在左边的小朋友顺序报数,直到数到某个数字M时就出圈。直到只剩下1个小朋友,则游戏完毕。
现在给定N,M,求N个小朋友的出圈顺序。
输入描述 Input Description
唯一的一行包含两个整数N,M。(1<=N,M<=30000)
输出描述 Output Description
唯一的一行包含N个整数,每两个整数中间用空格隔开,第I个整数表示第I个出圈的小朋友的编号。
样例输入 Sample Input
5 3
样例输出 Sample Output
类型:线段树 难度:33 1 5 2 4
题意:n个人围成一圈,顺时针编号1-n,给出一个m,从第1个人开始数,数到第m个人就出圈,然后从出圈的下一个人继续数m个。。。求出圈的顺序。
分析:用线段树存储每个区间中剩余的人数,即在圈内则置为1,出圈的置为0,用realm表示当前查找的是还在圈中的第几个人,即线段树(1,x)区间的和为realm,那么x就是这次出圈的人。例:若当前的序列为10110,realm=2,那么这次出圈的人是3。
计算realm:realm初始化为1,每次更新realm = (realm-2+m)%i+1,i=n,...,1,这个式子的解释:首先考虑(realm+m)%i为下一个查找realm,发现每次去掉一个人后,相当于从realm之前的一个人开始数,所以变成(realm-1+m)%i,但是%i的结果可能为0,所以在最后+1,前面再-1。
查找x满足(1,x)的和为realm,且x为1:类似二分查找,先查找线段树左子树的和,若小于等于realm,则x在左子树,递归查找;若大于realm,查找右子树,realm更新为realm-sum[left],直到查找区间的左右边界相等,即返回结果。
代码:
#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>using namespace std;#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn = 100010;int n,m;int sum[maxn<<2];void PushUP(int rt) {//把当前结点的信息更新到父结点 sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void build(int l,int r,int rt) {//建立线段树if (l == r) {sum[rt] = 1;return ;}int m = (l + r) >> 1;build(lson);build(rson);PushUP(rt);}void update(int p,int v,int l,int r,int rt) {//单点增减if (l == r) {sum[rt] = v;return ;}int m = (l + r) >> 1;if (p <= m) update(p , v , lson);else update(p , v , rson);PushUP(rt);}int findpos(int len,int l,int r,int rt) {//区间求和if (l==r) {return l;}int left = rt<<1;int m = (l+r)>>1;if(len <= sum[left]) return findpos(len,lson);return findpos(len-sum[left],rson);}int main(){ scanf("%d%d",&n,&m); build(1,n,1); int realm = 1,now; for(int i=n; i>0; i--) { realm = (realm-2+m)%i+1; now = findpos(realm,1,n,1); printf("%d ",now); update(now,0,1,n,1); } printf("\n");}
- wikioi-天梯-进入省队-线段树-1282:约瑟夫问题
- wikioi 1282 约瑟夫问题 线段树
- wikioi-天梯-进入省队-并查集-1073:家族
- wikioi-天梯-进入省队-树状dp-1163:访问艺术馆
- WIKIOI 1282 约瑟夫问题
- wikioi 1282 约瑟夫问题
- Wikioi 1282 约瑟夫问题
- wikioi约瑟夫问题c++
- 约瑟夫问题线段树
- wikioi天梯之1214 线段覆盖 贪心
- 1282 约瑟夫问题_线段树
- Codevs 1282 约瑟夫问题 线段树
- 线段树 约瑟夫问题 codevs 1282
- 【CODEVS】1282 约瑟夫问题(线段树)
- 约瑟夫问题(线段树)
- codevs1282 约瑟夫问题 线段树
- codevs1282 约瑟夫问题(线段树)
- Codevs_P1282 约瑟夫问题(线段树)
- c/c++如何获得数组的长度
- 关于实仓与虚仓和调拨单和虚仓调拨单的区别
- awk命令学习
- android 弹出多选对话框
- Android-java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.pr
- wikioi-天梯-进入省队-线段树-1282:约瑟夫问题
- Sitemesh入门
- ClientCnxn: Session 0x0 for server null, unexpected error 异常解决
- C#学习笔记:数据库编程1
- 从extenionplugin的C++ 模块中读取数据并显示到Qt的ListView上
- WIN7上搭建Windows Phone 8 开发环境——VMware Workstation下Win8 “无法安装Hyper-V, 某个虚拟机监控程序正在运行”问题解决的办法
- NoSQL数据库的35个应用场景
- 自己动手写分词引擎——逆向最大、正向最大、双向最大分词算法的实现
- Ubuntu openssh服务自动下载并安装