首页 > 代码库 > pojBuy Tickets2828线段树(队列中倒序插队)

pojBuy Tickets2828线段树(队列中倒序插队)

这题开始的思路就是模拟:就像数组中插点一样,每一个想买票的人都想往前插队!但是这样的话肯定TLE, 看了别人的思路之后才恍然大悟!正解:    将开始的正序插入,变成倒序插入,这样的话,想一想:第 i 个人想要插在 p[i]    的位置上,那么就要保证所插入的位置之前一定要有 p[i]-1个空位!因为一定会有p[j]<p[i]    (0<=p[j]<=j,每个人都想往前插队)     的第j个人插在p[i]的位置的前边!         如果i<j; && p[i]==p[j], 倒序插入中,第j个人先插入, 那么第i个人在保证插入的位置之前有    p[i]-1个空位的同时,又要插入到第 j 个人的后边! 

 



1
#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define M 200005 6 using namespace std; 7 8 pair<int, int>per[M]; 9 int ret[M]; 10 int tree[M*4];11 int n;12 13 void buildT(int p, int ld, int rd){14 if(ld==rd){15 tree[p]=1;16 return ;17 }18 int mid=(ld+rd)>>1;19 buildT(p<<1, ld, mid);20 buildT(p<<1|1, mid+1, rd);21 tree[p]=tree[p<<1]+tree[p<<1|1]; 22 }23 24 void updateT(int p, int ld, int rd, int pos, int val){25 if(ld==rd){26 tree[p]=0;27 ret[ld]=val;28 return ;29 }30 int mid=(ld+rd)>>1;31 if(tree[p<<1]>pos)32 updateT(p<<1, ld, mid, pos, val);33 else 34 updateT(p<<1|1, mid+1, rd, pos-tree[p<<1], val);35 36 tree[p]=tree[p<<1]+tree[p<<1|1]; 37 }38 39 int main(){40 int i;41 while(scanf("%d", &n)!=EOF){42 buildT(1, 1, n); 43 for(i=1; i<=n; ++i)44 scanf("%d%d", &per[i].first, &per[i].second);45 for(i=n; i>=1; --i)46 updateT(1, 1, n, per[i].first, per[i].second);47 48 printf("%d", ret[1]);49 for(i=2; i<=n; ++i)50 printf(" %d", ret[i]);51 printf("\n"); 52 }53 return 0;54 }