BZOJ 1109: [POI2007]堆积木Klo

1109: [POI2007]堆积木Klo

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 948  Solved: 341
[Submit][Status][Discuss]

Description

  Mary在她的生日礼物中有一些积木。那些积木都是相同大小的立方体。每个积木上面都有一个数。Mary用他的
所有积木垒了一个高塔。妈妈告诉Mary游戏的目的是建一个塔,使得最多的积木在正确的位置。一个上面写有数i
的积木的正确位置是这个塔从下往上数第i个位置。Mary决定从现有的高塔中移走一些,使得有最多的积木在正确
的位置。请你告诉Mary她应该移走哪些积木。

Input

  第一行为一个数n,表示高塔的初始高度。第二行包含n个数a1,a2,...,an,表示从下到上每个积木上面的数。
(1<=n<=100000,1<=ai<=1000000)。

Output

  注意:请输出最多有多少点可以处在正确位置

Sample Input

5
1 1 2 5 4

Sample Output

3

HINT

 

 

 

Source

 
[Submit][Status][Discuss]

 

分析

OTZ Neighthorn

一开始是三维——

i > j && a[i] > a[j] && a[i] - i <= a[j] - j

然后,巨机的Neighthorn告诉我们,这其实是二维,因为满足后两个条件时,第一维一定满足。

所以是二维了——

a[i] > a[j] && a[i] - i <= a[j] - j

然而蒟蒻的我依然不会,于是巨机的Neighthorn有开始指点迷津。

说,如果你把a[i]看作新的下标,这就是个水水的最长不严格上升子序列问题。

∑( 口 ||, 再次 OTZ Neighthorn。

代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 #define lim 10000000
 6 
 7 class Scanner
 8 {
 9     private:
10         char *c;
11         
12     public:
13         Scanner(void)
14         {
15             c = new char[lim];
16             fread(c, 1, lim, stdin);
17         }
18         
19         int nextInt(void)
20         {
21             int res = 0;
22             bool neg = 0;
23             
24             while (*c < '0')
25                 if (*c++ == '-')
26                     neg ^= true;
27             
28             while (*c >= '0')
29                 res = res*10 + *c++ - '0';
30                 
31             return neg ? -res : res;
32         }
33 }in;
34 
35 #define N 1000005
36 
37 int n, a[N];
38 
39 struct pair
40 {
41     int x, y;
42     pair(void) {};
43     pair(int a, int b) :
44         x(a), y(b) {};
45 };
46 
47 pair p[N];
48 
49 int cmp(const void *a, const void *b)
50 {
51     if (((pair *)a)->x != ((pair *)b)->x)
52         return ((pair *)a)->x - ((pair *)b)->x;
53     else return -((pair *)a)->y + ((pair *)b)->y;
54 }
55 
56 int tmp[N];
57 
58 #define inf 0x3f3f3f3f
59 #define low lower_bound
60 #define upp upper_bound
61 
62 signed main(void)
63 {
64     n = in.nextInt();
65     
66     for (int i = 1; i <= n; ++i)
67         a[i] = in.nextInt();
68         
69     for (int i = 1; i <= n; ++i)if (a[i] <= i)
70         p[i] = pair(a[i], i - a[i]);
71     else p[i] = pair(inf, inf);
72         
73     qsort(p + 1, n, sizeof(pair), cmp);
74     
75     using namespace std;
76     
77     memset(tmp, inf, sizeof(tmp));
78     
79     for (int i = 1; i <= n; ++i)
80     {
81         int t = p[i].y;
82         *upp(tmp, tmp + i, t) = t;
83     }
84     
85     printf("%d\n", low(tmp, tmp + n, inf) - tmp);
86 }
BZOJ_1109.cpp

 

@Author: YouSiki

posted @ 2016-11-22 23:21  YouSiki  阅读(370)  评论(0编辑  收藏  举报