【codevs1282】约瑟夫问题
题目描述
有编号从1到N的N个小朋友在玩一种出圈的游戏。开始时N个小朋友围成一圈,编号为I+1的小朋友站在编号为I小朋友左边。编号为1的小朋友站在编号为N的小朋友左边。首先编号为1的小朋友开始报数,接着站在左边的小朋友顺序报数,直到数到某个数字M时就出圈。直到只剩下1个小朋友,则游戏完毕。
现在给定N,M,求N个小朋友的出圈顺序。
唯一的一行包含两个整数N,M。(1<=N,M<=30000)
唯一的一行包含N个整数,每两个整数中间用空格隔开,第I个整数表示第I个出圈的小朋友的编号。
5 3
样例输出
3 1 5 2 4
很好想的一道题,就是求出每次需要出圈的人的排名,然后输出并删除。
然而N为30000怎么办?
网上的题解是线段树,然而线段树不能删除,过于麻烦。
于是想到Treap。
代码有点长,但很好理解。
需要注意rn是上次的排名,但是这次第一个人的排名却应该与rn相同,因为已经减少一个人,对应排名-1。
因此rn初始值为1。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
int l[30001] , r[30001] , num[30001] , si[30001] , rnd[30001] , tot , root;
void pushup(int k)
{
si[k] = si[l[k]] + si[r[k]] + 1;
}
void zig(int &k)
{
int t = l[k];
l[k] = r[t];
r[t] = k;
si[t] = si[k];
pushup(k);
k = t;
}
void zag(int &k)
{
int t = r[k];
r[k] = l[t];
l[t] = k;
si[t] = si[k];
pushup(k);
k = t;
}
void ins(int &k , int x)
{
if(!k)
{
k = ++tot;
num[k] = x;
si[k] = 1;
rnd[k] = rand();
return;
}
si[k] ++ ;
if(x < num[k])
{
ins(l[k] , x);
if(rnd[l[k]] < rnd[k])
zig(k);
}
else
{
ins(r[k] , x);
if(rnd[r[k]] < rnd[k])
zag(k);
}
}
void del(int &k , int x)
{
if(!k) return;
if(x == num[k])
{
if(l[k] * r[k] == 0)
k = l[k] + r[k];
else if(rnd[l[k]] < rnd[r[k]])
zig(k) , del(k , x);
else
zag(k) , del(k , x);
}
else if(x < num[k])
si[k] -- , del(l[k] , x);
else
si[k] -- , del(r[k] , x);
}
int getrank(int k , int x)
{
if(x == num[k]) return si[l[x]] + 1;
else if(x < num[k]) return getrank(l[k] , x);
else return getrank(r[k] , x) + si[l[x]] + 1;
}
int find(int k , int x)
{
if(x <= si[l[k]]) return find(l[k] , x);
else if(x > si[l[k]] + 1) return find(r[k] , x - si[l[k]] - 1);
else return num[k];
}
int main()
{
int n , m , i , rn = 1 , c;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ )
ins(root , i);
for(i = 1 ; i <= n ; i ++ )
{
rn = (rn + m - 2 + si[root]) % si[root] + 1;
c = find(root , rn);
printf("%d " , c);
del(root , c);
}
printf("\n");
return 0;
}
【codevs1282】约瑟夫问题的更多相关文章
- 【codevs1282】约瑟夫问题 Treap
题目描述 有编号从1到N的N个小朋友在玩一种出圈的游戏.开始时N个小朋友围成一圈,编号为I+1的小朋友站在编号为I小朋友左边.编号为1的小朋友站在编号为N的小朋友左边.首先编号为1的小朋友开始报数,接 ...
- 约瑟夫问题(java实现)
方法一.自定义的链表实现 package com.code.yuesefu; public class YueSeFuList { public static void main(String[] a ...
- Java 解决约瑟夫问题
约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,类似问题又称为约瑟夫环.又称“丢手绢问题”.) 有这样一个故事,15个教徒和15个非教徒在深海遇险必须讲 ...
- C#实现约瑟夫环问题
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace orde ...
- C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析
尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这 ...
- C语言链表实现约瑟夫环问题
需求表达:略 分析: 实现: #include<stdio.h> #include<stdlib.h> typedef struct node { int payload ; ...
- AC日记——约瑟夫问题 codevs 1282
1282 约瑟夫问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description 有编号从1到N的N个小 ...
- Have Fun with Numbers及循环链表(约瑟夫问题)
1. 循环链表(约瑟夫问题) https://github.com/BodhiXing/Data_Structure 2. Have Fun with Numbers https://pta.pate ...
- javascript中使用循环链表实现约瑟夫环问题
1.问题 传说在公元1 世纪的犹太战争中,犹太历史学家弗拉维奥·约瑟夫斯和他的40 个同胞被罗马士兵包围.犹太士兵决定宁可自杀也不做俘虏,于是商量出了一个自杀方案.他们围成一个圈,从一个人开始,数到第 ...
随机推荐
- linux网络编程tcp
之前学习的时候笔记没有保存好,这次重新编写一个案例. 客户端实现程序代码: #include <string.h> #include <stdlib.h> #include & ...
- [bzoj2588][count on a tree] (主席树+lca)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 图片下方出现多3px的原因及解决方法
产生原因:主要是因为图片的垂直对齐方式vertical-align引发的,默认值是baseline,默认为此值时图片下方就会多出3px. 解决方案: 1.将图片的垂直对齐方式vertical-alig ...
- Introduction to graph theory 图论/脑网络基础
Source: Connected Brain Figure above: Bullmore E, Sporns O. Complex brain networks: graph theoretica ...
- [LeetCode] Largest Divisible Subset 最大可整除的子集合
Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of ...
- [LeetCode] Rank Scores 分数排行
Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ra ...
- [LeetCode] Valid Parentheses 验证括号
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the inpu ...
- 如何创建一个简单的Visual Studio Code扩展
注:本文提到的代码示例下载地址>How to create a simple extension for VS Code VS Code 是微软推出的一款轻量级的代码编辑器,免费,开源,支持多种 ...
- .net(C#)中this关键字
使用this关键字引用成员变量使用this关键字在自身构造方法内部引用其它构造方法使用this关键字代表自身类的对象使用this关键字引用成员方法 在一个类的方法或构造方法内部,可以使用"t ...
- C#实现Levenshtein distance最小编辑距离算法
Levenshtein distance,中文名为最小编辑距离,其目的是找出两个字符串之间需要改动多少个字符后变成一致.该算法使用了动态规划的算法策略,该问题具备最优子结构,最小编辑距离包含子最小编辑 ...