1. 程式人生 > >洛谷P1233 木棍加工【單調棧】

洛谷P1233 木棍加工【單調棧】

www long pri mat pro type 否則 scanf tps

題目:https://www.luogu.org/problemnew/show/P1233

題意:

有n根木棍,每根木棍有長度和寬度。

現在要求按某種順序加工木棍,如果前一根木棍的長度和寬度都大於現在這根,那加工這一根就不需要準備時間,否則需要1分鐘準備時間。

問最少的準備時間。

思路:

現在題目要同時維護兩個單調不升序列的數目。對於一個屬性顯然可以通過排序保證他們是單調不升的。

只需在排好序之後求另一個屬性的單調不升序列的個數。

這裏需要知道Dilworth定理: 偏序集能劃分成的最少的全序集的個數與最大反鏈的元素個數相等。

也就是說最長不升子序列的數目等於最長上升子序列的長度,最長上升子序列的數目等於最長不升子序列的長度。

問題轉化成,對一個屬性不升排序,再找另一個屬性的最長上升子序列的長度。

用單調棧可以實現NlogN的求最長上升子序列長度,具體分析見導彈攔截。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<cmath> 
 9 #include<stack>
10
#include<queue> 11 #include<iostream> 12 13 #define inf 0x7fffffff 14 using namespace std; 15 typedef long long LL; 16 typedef pair<string, string> pr; 17 18 int n; 19 const int maxn = 5005; 20 struct node{ 21 int l, w; 22 }stick[maxn]; 23 int sss[maxn], cnt = 0; 24
25 bool cmp(node a, node b) 26 { 27 return a.l > b.l; 28 } 29 30 int main() 31 { 32 scanf("%d", &n); 33 for(int i = 1; i <= n; i++){ 34 scanf("%d%d", &stick[i].l, &stick[i].w); 35 } 36 37 sort(stick + 1, stick + 1 + n, cmp); 38 39 for(int i = 1; i <= n; i++){ 40 if(stick[i].w > sss[cnt - 1]){ 41 sss[cnt++] = stick[i].w; 42 //printf("%d\n", sss[cnt - 1]); 43 } 44 else{ 45 int pos = lower_bound(sss, sss + cnt, stick[i].w) - sss; 46 sss[pos] = stick[i].w; 47 } 48 } 49 printf("%d\n", cnt); 50 51 return 0; 52 }

洛谷P1233 木棍加工【單調棧】