1. 程式人生 > >UVA1471-Defense Lines(思維+STL)

UVA1471-Defense Lines(思維+STL)

具體實現 bound ber 單調序列 count 最優 demo a long ans

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 forti?cation 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 ?ring 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 ?rst 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 ?rst 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 }

UVA1471-Defense Lines(思維+STL)