POJ 2828 (线段树 单点更新) Buy Tickets

倒着插,倒着插,这道题是倒着插!

想一下如果 Posi 里面有若干个0,那么排在最前面的一定是最后一个0.

从后往前看,对于第i个数,就应该插在第Posi + 1个空位上,所以用线段树来维护区间空位的个数。

 

说一下那个坑爹的第56行的判断:

if(i > 1) printf(" ");

将输出的n个数用空格隔开,我感觉这是一个还算常用的写法啊,结果各种莫名TLE,加上输入挂也补救不回来。

去掉这个无谓的判断后,3594MS险过,加上输入挂3094MS,还算是起到了一定的加速作用。

 1 #include <cstdio>
 2 #include <ctype.h>
 3 
 4 const int maxn = 200000 + 10;
 5 
 6 int n, p[maxn], v[maxn], a[maxn];
 7 int sum[maxn << 2];
 8 
 9 inline int Scan()
10 {
11   char c = getchar();
12   while(!isdigit(c)) c = getchar();
13 
14   int x = 0;
15   while(isdigit(c)) {
16     x = x * 10 + c - '0';
17     c = getchar();
18   }
19   return x;
20 }
21 
22 void build(int o, int L, int R)
23 {
24     if(L == R) { sum[o] = 1; return; }
25     int M = (L + R) / 2;
26     build(o<<1, L, M);
27     build(o<<1|1, M+1, R);
28     sum[o] = sum[o<<1] + sum[o<<1|1];
29 }
30 
31 void update(int o, int L, int R, int p, int v)
32 {
33     if(L == R) { sum[o] = 0; a[L] = v; return; }
34     int M = (L + R) / 2;
35     if(sum[o<<1] >= p) update(o<<1, L, M, p, v);
36     else update(o<<1|1, M+1, R, p-sum[o<<1], v);
37     sum[o] = sum[o<<1] + sum[o<<1|1];
38 }
39 
40 int main()
41 {
42     //freopen("in.txt", "r", stdin);
43 
44     while(scanf("%d", &n) == 1)
45     {
46         build(1, 1, n);
47         for(int i = 0; i < n; i++)
48         {
49             p[i] = Scan();
50             v[i] = Scan();
51         }
52         for(int i = n - 1; i >= 0; i--) update(1, 1, n, p[i]+1, v[i]);
53         printf("%d", a[1]);
54         for(int i = 2; i <= n; i++)
55         {
56             //if(i > 1) printf(" ");
57             printf(" %d", a[i]);
58         }
59         printf("\n");
60     }
61 
62     return 0;
63 }
代码君

 

posted @ 2015-04-26 10:22  AOQNRMGYXLMV  阅读(125)  评论(0编辑  收藏  举报