洛谷P1233 木棍加工【單調棧】
阿新 • • 發佈:2019-05-14
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; 2425 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 木棍加工【單調棧】