codevs 1282 約瑟夫問題
首先,建樹,根節點 l = 1, r = n, sum = n;
sum 指的是在這個區間內 還剩下的人數。
主函式乙個 while 迴圈, 一直迴圈到根節點 為 0; 也就是所有人都出圈了。
另外:根節點的sum (tree[1].sum)代表還沒出圈的還有多少人。
我們可以將 圓圈看為乙個佇列,最後乙個人的後面是 1、
nxt 為 從當前點往後 m 個人之後(可能到了尾部又從1開始)第 nxt個人。並不是 編號為 nxt 的人。
比如:
現在隊列為 1 3 5 7。
2、4、6出圈了。
如果我nxt = 2, 那麼我指的是從佇列頭 開始往後2個人, 就是編號為3 的人。
搞清楚了這一點之後開始考慮如何找 當前佇列中第 nxt 個人。
利用change 操作, 從線段樹根節點往下走, 因為我們找的是 第 nxt 個人,所以,如果左邊節點裡面的人數 小於 nxt 那麼我們要找的人肯定在右邊節點。 就變成了 找右邊節點中的第 nxt - x 個人。 另外,我們走過的節點的 sum 需要–, 因為我們已經確定我們要找的人 在這個區間裡面了, 我們找到之後 另 這個人的 sum = 0; 表示沒有這個人了。 也可以 – , 反正這是最底層節點, sum = 1;
再利用change 返回我們找到的這個點的編號,就行了。
**:
#include
#include
#include
#include
#define l(x) (x << 1)
#define r(x) (x << 1 | 1)
using namespace std;
const int maxn = 30000 + 3;
int n, m;
struct ttree[maxn << 2];
void update(int p)
void build(int l, int r, int p)
int mid = (l+r)/2;
build(l,mid,l(p));
build(mid+1,r,r(p));
update(p);
return;
}int change(int x, int p = 1)
if(tree[l(p)].sum >= x)
return change(x,l(p));
else
return change(x-tree[l(p)].sum, r(p));
}int main()
return
0;}
Codevs 1282 約瑟夫問題
1282 約瑟夫問題 時間限制 1 s 空間限制 128000 kb 題目描述 description 有編號從1到n的n個小朋友在玩一種出圈的遊戲。開始時n個小朋友圍成一圈,編號為i 1的小朋友站在編號為i小朋友左邊。編號為1的小朋友站在編號為n的小朋友左邊。首先編號為1的小朋友開始報數,接著站在...
Codevs 1282 約瑟夫問題
時間限制 1 s 空間限制 128000 kb 題目等級 大師 master 有編號從1到n的n個小朋友在玩一種出圈的遊戲。開始時n個小朋友圍成一圈,編號為i 1的小朋友站在編號為i小朋友左邊。編號為1的小朋友站在編號為n的小朋友左邊。首先編號為1的小朋友開始報數,接著站在左邊的小朋友順序報數,直到...
wikioi 1282 約瑟夫問題
這道題所用到的資料結構應該是名次樹,名次樹可以由線段樹實現也可以由樹狀陣列實現。而對於類似這道題這樣的乙個只需要刪除和查詢操作的名次樹而言,可以用樹狀陣列實現,因為用樹狀陣列實現無論效率還是 複雜度都較線段樹而言更優,雖然演算法較線段樹而言更加巧妙。首先,這個資料結構需要乙個用於查詢第k名是什麼的函...