●POJ 2828 Buy Tickets
阿新 • • 發佈:2018-01-27
build scanf ticket strong blank else ont 就是 struct
題鏈:
http://poj.org/problem?id=2828
題解:
線段樹。
逆向考慮這個過程。最後的序列S共有n個元素。
先看最後一個人,如果他插入到第i位,那麽他最終的位置就是當前序列S的第i號位置,然後把這個位置去掉,得到新序列S‘。
再按上面的操作確定倒數第二個人的位置:
如果他插入到第j位,那麽他就在新序列S‘的第j個位置。
。。。。。。以此類推,可以確定出所有人的位置。
可以用線段樹去確定位置。
代碼:
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 200050 using namespace std; struct People{ int p,d; }P[MAXN]; struct SGT{ int ls[MAXN<<1],rs[MAXN<<1],siz[MAXN<<1],sz,rt; void build(int &u,int l,int r){ u=++sz; siz[u]=r-l+1; if(l==r) return; int mid=(l+r)/2; build(ls[u],l,mid); build(rs[u],mid+1,r); } void Reset(int n){ sz=rt=0; build(rt,1,n); } int Modify(int u,int l,int r,int k){ siz[u]--; if(l==r) return l; int mid=(l+r)/2; if(k<=siz[ls[u]]) return Modify(ls[u],l,mid,k); else return Modify(rs[u],mid+1,r,k-siz[ls[u]]); } }DT; int ANS[MAXN]; int main(){ int n; while(~scanf("%d",&n)){ DT.Reset(n); for(int i=1;i<=n;i++) scanf("%d%d",&P[i].p,&P[i].d); for(int i=n,p;i;i--){ p=DT.Modify(DT.rt,1,n,P[i].p+1); ANS[p]=P[i].d; } for(int i=1;i<n;i++) printf("%d ",ANS[i]); if(n) printf("%d\n",ANS[n]); } return 0; }
●POJ 2828 Buy Tickets