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 }
代码君

 

你可能感兴趣的:(poj)