ural 1521. War Games 2 约瑟夫环 SBT实现
2012-08-28 12:27
344 查看
1521. War Games 2Time Limit: 1.0 secondMemory Limit: 16 MB BackgroundDuring the latest war games (this story is fully described in the problem "War games") the Minister of Defense of the Soviet Federation comrade Ivanov had a good chance to make sure personally, that an alertness of the Soviet Army under his command is just brilliant. But there was a thing, that continued to worry him. Being an outstanding commander, he realized, that only physical conditions of the soldiers were demonstrated. So the time came to organize one more war games and examine their mental capacity.General Rascal was appointed to be responsible for the war games again. The general donated the allocated funds to the poor and went to bed free-hearted. In his dream, the tactics manual appeared to him and described a scheme, that allows to organize the war games absolutely free of charge. ProblemIn accordance with this scheme, the war games are divided into N phases; and Nsoldiers, successively numbered from 1 to N, are marching round a circle one after another, i.e. the first follows the second, the second follows the third, ..., the (N-1)-th follows the N-th, and the N-th follows the first. At each phase, a single soldier leaves the circle and goes to clean the WC, while the others continue to march. At some phase, the circle is left by a soldier, who is marching K positions before the one, who left the circle at the previous phase. A soldier, whose number is K, leaves the circle at the first phase.Surely, Mr. Rascal cherished no hope about his soldiers' abilities to determine an order of leaving the circle. "These fools can not even paint the grass properly", - he sniffed scornfully and went to sergeant Filcher for an assistance. InputThe only line contains the integer numbers N (1 ≤ N ≤ 100000) and K (1 ≤ K ≤ N).OutputYou should output the numbers of soldiers as they leave the circle. The numbers should be separated by single spaces.Sample
|
N个人围成一圈顺序编号,从1号开始按1、2、3......顺序报数,报p者退出圈外,其余的人再从1、2、3开始报数,报p的人再退出圈外,以此类推。
请按退出顺序输出每个退出人的原序号。
输入:
包括一个整数N(1<=N<=100000)及一个整数p。
输出:
测试数据可能有多组,对于每一组数据,
按退出顺序输出每个退出人的原序号。
样例输入:
5 3
样例输出:
3 1 5 2 4
分析:
先把所有人插入到SBT中,然后出去的时候,把他从SBT中删除,而找到要删除的元素为pos = (pre+k-1)%n+1,n每出去一个人减一,而pre从0开始,若已经有人出队,则置为上一个人出队的位置减一,然后就是找到第pos小即可
代码如下:
View Code
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int X = 100005; int root,tol,n,m; struct node{ int val,l,r,s; void init(int _val){ l = r = 0; s = 1; val = _val; } }sbt[X]; void left_rotate(int &t){ int k = sbt[t].r; sbt[t].r = sbt[k].l; sbt[k].l = t; sbt[k].s = sbt[t].s; sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; t = k; } void right_rotate(int &t){ int k = sbt[t].l; sbt[t].l = sbt[k].r; sbt[k].r = t; sbt[k].s = sbt[t].s; sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; t = k; } void maintain(int &t,bool ok){ if(!ok){ if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) right_rotate(t); else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ left_rotate(sbt[t].l); right_rotate(t); } else return; } else{ if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) left_rotate(t); else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ right_rotate(sbt[t].r); left_rotate(t); } else return; } maintain(sbt[t].l,0); maintain(sbt[t].r,1); maintain(t,0); maintain(t,1); } void insert(int &t,int val){ if(!t){ t = ++tol; sbt[t].init(val); return; } sbt[t].s++; if(val<sbt[t].val) insert(sbt[t].l,val); else insert(sbt[t].r,val); maintain(t,val>=sbt[t].val); } int del(int &t,int val){ if(!t) return 0; sbt[t].s--; if(val==sbt[t].val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ if(sbt[t].l&&sbt[t].r){ int pos = del(sbt[t].l,val+1); sbt[t].val = sbt[pos].val; return pos; } else{ int pos = t; t = sbt[t].l+sbt[t].r; return pos; } } else return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); } int find_k_min(int &t,int k){ //找到第k小 if(k<=sbt[sbt[t].l].s) return find_k_min(sbt[t].l,k); else if(k>sbt[sbt[t].l].s+1) return find_k_min(sbt[t].r,k-sbt[sbt[t].l].s-1); else return sbt[t].val; } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); while(cin>>n>>m){ int pos = 0,temp,val; root = tol = 0; for(int i=1;i<=n;i++) insert(root,i); while(n){ temp = (pos+m-1)%n+1; pos = temp-1; val = find_k_min(root,temp); del(root,val); printf("%d",val); if(n>1) putchar(' '); n--; } puts(""); } return 0; }
相关文章推荐
- URAL 1521 War Games 2 树状数组解决约瑟夫环,输出离队顺序
- SBT解决约瑟夫环问题(URAL1521)
- Ural 1521. War Games 2
- Ural1521-War Games 2
- Java实现约瑟夫环
- 【c++】约瑟夫环的一维数组实现
- C/C++,数据结构单链表实现约瑟夫环
- Josephus(约瑟夫环问题)循环单链表c语句实现!
- Size Balanced Tree(SBT) 类模板C++实现(持续更新)
- C链表实现约瑟夫环
- Java实现约瑟夫环问题
- 约瑟夫环问题的实现
- 约瑟夫环(数组模拟实现)
- 循环链表实现约瑟夫环
- PHP实现约瑟夫环
- C/C++,数据结构单链表实现约瑟夫环
- 无聊闲做,从使用PHP数组实现约瑟夫环问题谈性能
- 用链表实现约瑟夫环
- 使用循环链表实现约瑟夫环
- 学习笔记之约瑟夫环的两种实现方法(数组&链表)