當前位置:
首頁 >
51nod 1102 面积最大的矩形 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))
發布時間:2024/4/19
40
豆豆
生活随笔
收集整理的這篇文章主要介紹了
51nod 1102 面积最大的矩形 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題面1:

題面2:

兩道題除了數據范圍不同,沒有任何差異,兩道題都可以o(n)(單調棧),o(nlog(n))(我自己的做法)解決。
解題思路1:(單調棧)
代碼1:
#include <bits/stdc++.h> using namespace std; typedef long long ll; //在新疆大學OJ提交需要將此處三個數組改為500010,否則會運行超時 ll a[50010]; int l[50010],r[50010]; int main(){ios::sync_with_stdio(false);int n;cin >> n;ll ans = 0;for(int i = 1;i <= n; ++i){cin >> a[i];}a[0] = a[n+1] = -1;stack<int> s;s.push(1);for(int i = 2;i <= n+1; ++i){if(a[i] < a[s.top()]){while(s.size() and a[i] < a[s.top()]){r[s.top()] = i;s.pop();}}s.push(i);}while(s.size()) s.pop();s.push(n);for(int i = n-1;i >= 0; --i){if(a[i] < a[s.top()]){while(s.size() and a[i] < a[s.top()]){l[s.top()] = i;s.pop();}}s.push(i);}for(int i = 1;i <= n; ++i){ans = max(ans, (a[i]*(r[i]-l[i]-1)));}cout << ans << endl;return 0; }解題思路2:(拼湊段)
遍歷這個結構體數組(這時數字是從大到下的),段(一個結構體,有l,r,used三個成員變量,l指這個段的左端位置,r指這個段的右端位置)
a. 若這個數字的原位置的左右邊兩個數字都已形成段,則將這兩段拼成一段,具體做法是將左邊段的r延長至右端,當前數字為這一段的最小值,更新ans。
b. 若這個數字的原位置的左邊形成段,右邊沒有形成段,則把這個數字加入到左邊的段,當前數字為這一段的最小值,更新ans。
c. 若這個數字的原位置的右邊形成段,左邊沒有形成段,則把這個數字加入到右邊的段,當前位置為這一段的最小值,更新ans。
d. 若這個數字的原位置的左邊和右邊都沒有形成段,則把這個數字加入到一個新的段,新的段的l和r都等于這個數字的原先位置,更新ans。
可能會想到查找左邊位置所處的段和右邊所處的段需要o(n)處理起來會變成o(n^2),這時候我們加一個索引數組index,index[i]表示位置為i的數字所處的段。
代碼2:
#include <bits/stdc++.h> using namespace std; typedef long long ll; //在新疆大學OJ提交需要將此處的50010全部改為500010 //輸入的數組,val為這個點的數字,idx表示原下標。 struct node{ll val;int idx; }a[50010]; //段,l表示左端,r表示右端 ,k表示段的個數。 struct segment{int l;int r; }seg[50010]; int k = 1; //index[i]表示第i個位置數字所處的段。 int index[50010];int n; bool cmp(node x,node y){return x.val > y.val; }int main(){ios::sync_with_stdio(false);int n;cin >> n;ll ans = 0;for(int i = 1;i <= n; ++i){cin >> a[i].val;a[i].idx = i;ans = max(ans , a[i].val);}sort(a+1, a+1+n, cmp);for(int i = 1;i <= n; ++i){int idxl = index[a[i].idx-1];int idxr = index[a[i].idx+1];if(idxl != 0 and idxr != 0){ //左右邊都形成一段。 seg[idxl].r = seg[idxr].r;index[seg[idxr].r] = idxl;ans = max(ans, a[i].val*(seg[idxl].r-seg[idxl].l+1));}else if(idxl != 0 and idxr == 0){ //左邊形成段,右邊未形成。 seg[idxl].r++;index[a[i].idx] = idxl;ans = max(ans, a[i].val*(seg[idxl].r-seg[idxl].l+1));}else if(idxl == 0 and idxr != 0){ //右邊形成段,左邊未形成。 seg[idxr].l--;index[a[i].idx] = idxr;ans = max(ans, a[i].val*(seg[idxr].r-seg[idxr].l+1));}else if(idxl == 0 and idxr == 0){ //左右邊均未形成段。 seg[k].l = a[i].idx;seg[k].r = a[i].idx;index[a[i].idx] = k; k++;}}cout << ans << endl;return 0; }總結
以上是生活随笔為你收集整理的51nod 1102 面积最大的矩形 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces 988E. Div
- 下一篇: 51nod 1158 全是1的最大子矩阵