UVA1471-Defense Lines(思维+STL)

Problem UVA1471-Defense Lines

Accept: 297  Submit: 2776
Time Limit: 9000 mSec

Problem Description

After the last war devastated your country, you - as the king of the land of Ardenia - decided it was high time to improve the defense of your capital city. A part of your fortification is a line of mage towers, starting near the city and continuing to the northern woods. Your advisors determined that the quality of the defense depended only on one factor: the length of a longest contiguous tower sequence of increasing heights. (They gave you a lengthy explanation, but the only thing you understood was that it had something to do with firing energy bolts at enemy forces). After some hard negotiations, it appeared that building new towers is out of question. Mages of Ardenia have agreed to demolish some of their towers, though. You may demolish arbitrary number of towers, but the mages enforced one condition: these towers have to be consecutive. For example, if the heights of towers were, respectively, 5, 3, 4, 9, 2, 8, 6, 7, 1, then by demolishing towers of heights 9, 2, and 8, the longest increasing sequence of consecutive towers is 3, 4, 6, 7.

Input

The input contains several test cases. The first line of the input contains a positive integer Z ≤ 25, denoting the number of test cases. Then Z test cases follow, each conforming to the format described below. The input instance consists of two lines. The first one contains one positive integer n ≤ 2 · 105 denoting the number of towers. The second line contains n positive integers not larger than 109 separated by single spaces being the heights of the towers.

 Output

For each test case, your program has to write an output conforming to the format described below. You should output one line containing the length of a longest increasing sequence of consecutive towers, achievable by demolishing some consecutive towers or no tower at all.

 Sample Input

2
9
5 3 4 9 2 8 6 7 1
7
1 2 3 10 4 5 6
 

 Sample Output

4
6

题解:好题!首先是算法设计过程中的优化,将不可能成为最优解的情况删去,使得所有可能最优解构成单调序列,即可二分将复杂度从O(n^2)降到O(nlogn).

其次就是实现时的技巧,这里结构体中 < 的设计时精髓,我原来总是想着把它定义的尽量严谨,对任意的情况都能准确找到二者的关系,但是有时候并不方便,这里只将 < 定义得与val有关,方便之处就体现在可以实现val的严格单调,具体原因我们可以来分析一下为什么只定义 < 就可以实现所有关系。

紫书中在第五章给出了符号重载的具体实现,当有了 < 之后 >= 就意味着 !< ,但是这里只有在val严格递增时 < 才会成立,因此如果两个Candidiate的val相同的话,<= 和 >= 都会成立,这时再看 == 的定义,发现它会返回true,也就是说,只要val相同就会返回true,这样在set里就不会有val相同的情况,只可能严格增,这正是我们想要的。这个操作大大简化了各种if else判断,mark下来。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 2 * 100000 + 100;
 6 
 7 int n, num[maxn];
 8 int f[maxn], g[maxn];
 9 
10 struct Candidate {
11     int val, lon;
12     Candidate(int val = 0, int lon = 0) : val(val), lon(lon) {}
13     bool operator < (const Candidate &a)const {
14         return val < a.val;
15     }
16 };
17 
18 set<Candidate> iset;
19 
20 int main()
21 {
22     //freopen("input.txt", "r", stdin);
23     int iCase;
24     scanf("%d", &iCase);
25     while (iCase--) {
26         scanf("%d", &n);
27         for (int i = 0; i < n; i++) {
28             scanf("%d", &num[i]);
29         }
30 
31         if (n == 1) {
32             printf("1\n"); continue;
33         }
34 
35         g[0] = 1;
36         for (int i = 1; i < n; i++) {
37             if (num[i] > num[i - 1]) g[i] = g[i - 1] + 1;
38             else g[i] = 1;
39         }
40 
41         f[n - 1] = 1;
42         for (int i = n - 2; i >= 0; i--) {
43             if (num[i] < num[i + 1]) f[i] = f[i + 1] + 1;
44             else f[i] = 1;
45         }
46 
47         int ans = 1;
48 
49         iset.clear();
50         iset.insert(Candidate(num[0], g[0]));
51         for (int i = 1; i < n; i++) {
52             Candidate v(num[i],g[i]);
53             set<Candidate>::iterator iter = iset.lower_bound(v);
54             bool keep = true;
55             if (iter != iset.begin()) {
56                 Candidate pre = *(--iter);
57                 int len = pre.lon + f[i];
58                 ans = ans > len ? ans : len;
59                 if (v.lon <= pre.lon) keep = false;
60             }
61 
62             if (keep) {
63                 iset.erase(v);
64                 iset.insert(v);
65                 set<Candidate>::iterator it = iset.find(v);
66                 it++;
67                 while (it != iset.end() && it->val > v.val && it->lon <= v.lon) {
68                     iset.erase(it++);
69                 }
70             }
71         }
72         printf("%d\n", ans);
73     }
74     return 0;
75 }

猜你喜欢

转载自www.cnblogs.com/npugen/p/9649116.html