poj2828--Buy Tickets
題目描述
Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue…
The Lunar New Year was approaching, but unluckily the Little Cat still had schedules going here and there. Now, he had to travel by train to Mianyang, Sichuan Province for the winter camp selection of the national team of Olympiad in Informatics.
It was one o’clock a.m. and dark outside. Chill wind from the northwest did not scare off the people in the queue. The cold night gave the Little Cat a shiver. Why not find a problem to think about? That was none the less better than freezing to death!
People kept jumping the queue. Since it was too dark around, such moves would not be discovered even by the people adjacent to the queue-jumpers. “If every person in the queue is assigned an integral value and all the information about those who have jumped the queue and where they stand after queue-jumping is given, can I find out the final order of people in the queue?” Thought the Little Cat.
題目大意
有N個人排隊,每一個人都有一個val來對應,每一個後來人都會插入當前隊伍的某一個位置pos。要求把隊伍最後的狀態輸出。
解法
其實想到正解其實很簡單,因為前面的每一個人都可能受到後面的人的插入而改變,那麽我們可以確定這個序列之中,我們最先確定一定是最後的人,那麽我們就解決了第一個問題。
但是我們還是不清楚這個線段樹是要怎麽建。但是仔細一想,如果我們要確定當前這個人的位置,那麽我們必須要知道他前面一共有多少空格,這就是我們需要維護的東西。
來看一張圖片,來自著名的hzwer大大的博客(p≧w≦q)!!!
這張圖片解釋了樣例1,那麽我們來詳細說明一下。
再重申一下我們要維護的是區間內的空出來的位置。如果當前這個左區間內可以放入我們的這個人,那麽我們就把這個人這個區間內,往下遞歸,不行那麽放到有區間內,其實也就是通過當前這個區間的空格的個數來確定這個人是否可以放到哪個地方。這樣不存在問題,是因為越後面的越不會受到影響,那麽後面的都排好了,那麽這個人就不會受到影響。然後每一次處理完一個人,那麽就將這個區間的空格減少一個。
非常完美的做法。
ac代碼
#include<cstdio>
#include<cstring>
#include<iostream>
#include<ctype.h>
#define N 200005
#define lson nod<<1
#define rson nod<<1|1
using namespace std;
struct Segment_tree{
int tree[N<<2],ans[N];
void init(){memset(tree,-1,sizeof(tree));}
void pushup(int nod){tree[nod]=tree[lson]+tree[rson];}//pushup函數
void build(int l,int r,int nod){//構建各個人前空格的線段樹
if(l==r){tree[nod]=1;return;}
int mid=l+r>>1;
build(l,mid,lson); build(mid+1,r,rson);
pushup(nod);
}
void update(int l,int r,int k,int v,int nod){//單點更新
if(l==r){ans[l]=v;tree[nod]=0;return;}//走到根節點就把這個人放到這個位置
int mid=l+r>>1;
if(tree[lson]>=k) update(l,mid,k,v,lson);//如果左邊足夠,那麽就放到左邊
else update(mid+1,r,k-tree[lson],v,rson);//左邊不夠,放到右邊去
pushup(nod);//更新維護線段樹
}
}T;
int r(){
int w=0,x=0;char ch=0;
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return w?-x:x;
}
int x[N],v[N],n;
int main(){
while(~scanf("%d",&n)){
T.init(); T.build(1,n,1);
for(int i=1;i<=n;i++) x[i]=r(),v[i]=r(),x[i]++;//說明當前人需要排到當前這個序列的x[i]的位置
for(int i=n;i>=1;i--) T.update(1,n,x[i],v[i],1);
for(int i=1;i<=n;i++) printf("%d ",T.ans[i]);
puts("");
}
return 0;
}
poj2828--Buy Tickets