poj 2828 Buy Tickets 【線段樹點更新】
阿新 • • 發佈:2017-05-17
clu input family freopen rst cst href targe pri
題目:poj 2828 Buy Tickets
題意:有n個人排隊,每一個人有一個價值和要插的位置,然後當要插的位置上有人時全部的人向後移動一位當這個插入到這兒,假設沒有直接插進去。
分析:分析發現直接插入移動的話花時間太多。我們可不能夠用逆向思維。
從後往前來。由於最後一個位置是肯定能確定的,而其它的則插入空的第某個位置。
比方第一組例子:
4 0 77 1 51 1 33 2 69
開始時候位置都為空 編號0 1 2 3
首先從最後一個來2 69第二個位置空,則能夠直接放
然後編號變為0 1 69 2
接著放1 33
編號變為 0 33 69 1
然後放1 51
編號變為0 33 69 51
然後放最後一個0 77
則最後結果為 77 33 69 51
能夠發現該怎麽搞了。就是直接用線段樹來維護區間上的值。然後選擇插入對應的位置就可以。
AC代碼:
#include <cstdio> #include <vector> #include <iostream> using namespace std; typedef long long LL ; const int N = 220000; struct Node { int l,r; int val,num; }; Node tree[5*N]; void build(int o,int l,int r) { tree[o].l = l,tree[o].r = r; if(l==r) { tree[o].val = 1; return ; } int mid = (l+r)/2; build(o+o,l,mid); build(o+o+1,mid+1,r); tree[o].val = tree[o+o].val + tree[o+o+1].val; } void update(int o,int num,int val) { //printf("%d %d %d %d\n",o,tree[o].l,tree[o].r,tree[o].val); if(tree[o].l==tree[o].r) { tree[o].num = val; tree[o].val = 0; return ; } if(tree[o+o].val>=num) update(o+o,num,val); else update(o+o+1,num-tree[o+o].val,val); tree[o].val = tree[o+o].val + tree[o+o+1].val; } vector<int> ans; void Yougth(int o) { if(tree[o].l==tree[o].r) { ans.push_back(tree[o].num); return ; } Yougth(o+o); Yougth(o+o+1); } pair <int,int> p[N]; int main() { //freopen("Input.txt","r",stdin); int n; while(~scanf("%d",&n)) { build(1,1,n); for(int i=0;i<n;i++) { int x,y; scanf("%d%d",&x,&y); x++; p[i] = make_pair(x,y); } for(int i=n-1;i>=0;i--) update(1,p[i].first,p[i].second); Yougth(1); for(int i=0;i<ans.size();i++) printf("%d%c",ans[i],i==(ans.size()-1)?‘\n‘:‘ ‘); ans.clear(); } return 0; }
poj 2828 Buy Tickets 【線段樹點更新】