poj2828Buy Tickets(线段树 单点更新+区间求和+区间第K值)

http://poj.org/problem?id=2828

险过 3500+ms

第i个人入队 只影响后面的不会影响前面的 可以倒推 全初始化为1 第i个人去第k位置 由于是倒推,第k个位置为0,表示求k-1位置的时候不能算上k位置的人 根据区间和 求出区间第K值 就是第i个人要放的位置

View Code
 1 #include <iostream>

 2 #include<cstdio>

 3 #include<string.h>

 4 using namespace std;

 5 #define N 200001

 6 int s[N*4],d[N*2][2],po[N*2],j;

 7 void build(int l,int r,int w)

 8 {

 9     if(l==r)

10     {

11         s[w] = 1;

12         return ;

13     }

14     int m = (l+r)/2;

15     build(l,m,2*w);

16     build(m+1,r,2*w+1);

17 }

18 void upset(int l,int r,int w)

19 {

20     if(l==r)

21     return ;

22     int m  =(l+r)/2;

23     upset(l,m,2*w);

24     upset(m+1,r,2*w+1);

25     s[w] = s[w*2]+s[2*w+1];

26 }

27 void add(int p,int da,int l,int r,int w)

28 {

29     if(l==r)

30     {

31         s[w] = 0;

32         po[l] = da;

33         return ;

34     }

35     int m= (l+r)/2;

36     if(p<=s[w*2])

37     add(p,da,l,m,2*w);

38     else

39     add(p-s[w*2],da,m+1,r,2*w+1);

40     s[w] = s[2*w]+s[w*2+1];

41 }

42 int main()

43 {

44     int n,i,k,m;

45     while(scanf("%d",&n)!=EOF)

46     {

47         j =0;

48         memset(po,0,sizeof(po));

49         for(i = 1; i <= n ; i++)

50         scanf("%d%d", &d[i][0],&d[i][1]);

51         build(1,n,1);

52         upset(1,n,1);

53         for(i = n ; i >= 1; i--)

54         add(d[i][0]+1,d[i][1],1,n,1);

55         for(i = 1 ; i < n ; i++)

56         printf("%d ",po[i]);

57         printf("%d\n",po[n]);

58     }

59     return 0;

60 }

 

 

你可能感兴趣的:(poj)