摘要

题目链接 难度等级 完成状态 完成分数 最后编辑时间 失误原因(初次提交分数)
约瑟夫问题 ★☆☆☆☆ 答案正确 100 2015-3-29 21:26:45 数组不够大(40)

题意

N个小朋友围一圈,每次点到第k个出列,问出列顺序。

题解

  • 我们设定小朋友有两个编号,一个是原始编号i,另一个是在剔除掉一些小朋友后的编号i',每个小朋友后是否在圈中记为p。e.g.
显示/移除行号
  1. 原始编号
  2. i 1 2 3 4 5
  3. i' 1 2 3 4 5
  4. p 1 1 1 1 1
  5. 剔除掉第3个小朋友的编号
  6. i 1 2 3 4 5
  7. i' 1 2 x 3 4
  8. p 1 1 0 1 1

容易知道i'是p的前缀和。可以用线段树处理问题。

代码

1282.cpp代码已折叠
展开折叠内容
显示/移除行号
  1. #include<stdio.h>
  2. #include<algorithm>
  3. using namespace std;
  4. template<size_t N>
  5. class SegmentTree
  6. {
  7. //模板:线段树//
  8. public:
  9. int tree[N];
  10. int lazy[N];
  11. #define lchild rt << 1, l, m
  12. #define rchild rt << 1 | 1, m + 1, r
  13. void push_up(int rt) {
  14. tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
  15. }
  16.  
  17. int build(int rt,int l,int r,int ex)
  18. {
  19. if(l==r)
  20. { if(ex!=l)
  21. return tree[rt]=1;
  22. else
  23. return tree[rt]=1e+7;
  24. }
  25. int m=(l+r)>>1;
  26. return tree[rt]=build(lchild,ex)+build(rchild,ex);
  27. }
  28. void push_down(int rt, int len) {
  29. tree[rt << 1] += lazy[rt] * (len - (len >> 1));
  30. lazy[rt << 1] += lazy[rt];
  31. tree[rt << 1 | 1] += lazy[rt] * (len >> 1);
  32. lazy[rt << 1 | 1] += lazy[rt];
  33. lazy[rt] = 0;
  34. }
  35. void push_down(int rt) {
  36. tree[rt << 1] += lazy[rt];
  37. lazy[rt << 1] += lazy[rt];
  38. tree[rt << 1 | 1] += lazy[rt];
  39. lazy[rt << 1 | 1] += lazy[rt];
  40. lazy[rt] = 0;
  41. }
  42. void update(int L, int R, int delta, int rt , int l , int r ) {
  43. if (L <= l && r <= R) {
  44. tree[rt] += delta * (r - l + 1);
  45. lazy[rt] += delta;
  46. return;
  47. }
  48. if (lazy[rt]) push_down(rt, r - l + 1);
  49. int m = (l + r) >> 1;
  50. if (L <= m) update(L, R, delta, lchild);
  51. if (R > m) update(L, R, delta, rchild);
  52. push_up(rt);
  53. }
  54. int query(int L, int R, int rt , int l , int r ) {
  55. if (L <= l && r <= R) return tree[rt];
  56. if (lazy[rt]) push_down(rt, r - l + 1);
  57. int m = (l + r) >> 1, ret = 0;
  58. if (L <= m) ret += query(L, R, lchild);
  59. if (R > m) ret += query(L, R, rchild);
  60. return ret;
  61. }
  62. };
  63. SegmentTree<33333> tre={};
  64. int n,k;
  65. int biSearch(int l,int r,int last)
  66. {
  67. if(l==r)return l;
  68. if(r<=0)return -1e+6;
  69. if(tre.query(1,m,1,1,n+1)<last)
  70. return biSearch(m+1,r,last);
  71. else
  72. return biSearch(l,m,last);
  73. }
  74. int main()
  75. {
  76. scanf("%d%d",&n,&k);
  77. tre.build(1,1,n+1,n+1);
  78. int last=0,least=n,lasti;
  79. for(int i=1;i<=n;++i,--least)
  80. {
  81. last=(last+k-1)%least+1;
  82. lasti=biSearch(1,n+1,last);
  83. tre.update(lasti,lasti,-1,1,1,n+1);
  84. printf("%d ",lasti);
  85. --last;
  86. }
  87. }

著作权声明[编辑]

关于[编辑]