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 }
原文地址:https://www.cnblogs.com/shangyu/p/2671754.html