POJ2828 Buy Tickets 線段樹好題

2022-05-15 02:23:28 字數 1846 閱讀 9219

poj2828 buy tickets

題意:插隊問題;

關鍵:如何插入這幾個節點,每個節點儲存什麼資訊。

型別:很基本的單點更新線段樹

思路:這題想到了就水了,資料逆著插入,最先插入的乙個資料的位置明顯是題目給定的位置,可以確定,然後插入的幾個數根據的位置前面插入的資料來決定,

用sum陣列表示改線段空位置的個數,滿足 pos<=sum[rt<<1](即左兒子的空位多於插入數的位置序號)就訪問左兒子,否則訪問右兒子

(訪問右節點的時候注意pos要修改,改為pos-sum[rt],即整個線段的第pos個空位,在下乙個右兒子那的第pos-sum[rt]個空位)。

對自己的總結: 剛學線段樹,誒,這題刷了一下午,看來線段樹的基礎還不夠,要加油了;

下面是我的ac**。

view code

#include#include

#define lson l, m, rt<<1

#define rson m+1, r, rt<<1|1

#define mid int m = (l + r)>>1

#define maxn 200000

int sum[maxn<<2],pos[maxn],val[maxn],ans[maxn<<2];//

ans儲存插入的值;

void push_up(int

rt)void build(int l, int r, int

rt)void update(int pos, int val, int l, int r, int

rt) mid;

if(pos <= sum[rt<<1])update(pos, val, lson); //

根據左右兒子空位的多少和插入資料的位置比較來確定插入哪個兒子

else update(pos -sum[rt<<1

], val, rson);

push_up(rt);

}void print(int l, int r, int

rt) mid;

print(lson);

print(rson);

}int

main()

return0;

}

還有一種是節點記錄已占有的位置(即非空位),cnt[rt]+pos<=m訪問左節點,否則就訪問右兒子(訪問右兒子時節點修改為cnt[rt]+pos);

view code

#include#include

#define lson l, m, rt<<1

#define rson m+1, r, rt<<1|1

#define mid int m = (l + r)>>1

#define maxn 200000

int cnt[maxn<<2],ans[maxn<<2

],pos[maxn],val[maxn];

void update(int pos, int val, int l, int r, int

rt) mid;

if(pos + cnt[rt<<1] <=m)update(pos, val, lson);

else update(pos+cnt[rt<<1

], val, rson);

}void print(int l, int r, int

rt) mid;

print(lson);

print(rson);

}int

main()

print(

1, n, 1

); printf("\n

");}

return0;

}

POJ 2828解題報告

題目不再重述。我也是看了解題報告的.之前怎麼都想不到,如果正常模擬的話,每一次插入元素都必須準確的知道位置在pos的元素究竟是哪乙個,知道連在那乙個元素後面,才能正確的串成乙個隊嘛。如果用陣列 向中間加元素要乙個乙個的挪 用鍊錶 n 2 超時了。其他的資料結構?怎麼都想不到一種可以動態維護記錄每個元...

線段數應用 poj2828

線段數應用 題目 buy tickets 題目大意 n個人排隊等待,第 i個人到來會有兩個資訊 pos i 0,i 1 val i 表明這 個人會插隊到 pos i 的後邊,這個人的值是 val i 依次給出 n個人的到來資訊,輸出最終的 佇列從頭到尾每個人的值。思路 第 i個人插入的位置是 pos...

poj2828 無鍵跳表

所以我覺得這個題吧,其實正解是個跳表。1.首先我們不考慮跳表,考慮二叉搜尋樹。如果這個題用二叉搜尋樹,怎麼做呢?考慮一下啊。首先很容易知道每個人名字和點的鍵值key是沒關係的對吧。那麼人的名字就只能作為value了對吧。那我們需要個key。那麼,key要保證什麼條件呢?很明顯每次插進去乙個點q,插在...