历史的进程 Week 1 题解

zerol edited 7 年,6 月前

A. Maximum Element

方案1:再开一个 multiset 记录当前栈中的元素,以便查询最大元素,当然这么做平白无故多出了个常数的复杂度($lgn$),虽然不影响AC。
方案2:再开一个 stack 用于存放最大元素,下面我粘贴一段英文题解(真·官方题解)
The approach is pretty straight forward. We keep two stacks: One is for pushing and popping elements as they come and go (elements stack), and the other is for keeping track of the maximum element (maximum elements stack).

When the first element arrives, push it onto both of the stacks. As the elements may not be distinct, we need to keep track of their indices. So, declare a stack of pair<int, int> or use a structure.

We maintain the maximum elements stack so that the maximum element till now is on the top. Whenever we push an element, it normally goes to the elements stack, but we also push it to the maximum elements stack if, and only if, it is greater than the current maximum element.

Now, when an element is to be deleted, we pop it directly from the elements stack. We also check if that particular element is the maximum element or not. We do so by comparing the value and the index of the popped element with the element on top of the maximum elements stack. If they are equal, we pop that element as well.

Finally, to answer the maximum element query 3, we print the element on top of the maximum elements stack.

B. Rails

参考入门经典P180
书上有核心代码,所以标程就不贴了。

C. Balanced Brackets

这个太简单了,肯定难不住会逆波兰(后缀)表达式求值的你们。
如果感到疑惑请直接看代码。

D. 向右看齐

单调栈。建议大家去网上搜一搜相关内容。

E. 锯栅栏

哈夫曼树。
具体请参考入门经典P234

F. 奶牛优惠券

这道题目有点难.
贴一个网上的题解

G. 都市地平线

按照端点排序,然后再从左到右扫一遍,同时维护一个存放建筑高度的 multiset(遇到建筑的左端点便将其高度加入 set,遇到右端点便将其从 set 中移除),这样我们又能知道每两个端点间建筑的最高高度了。

A. Maximum Element

set大法

#include <bits/stdc++.h>
using namespace std;
multiset<int> St;
stack<int> Sk;
int n, t, k;

int main() {
    #ifdef zerol
    freopen("in", "r", stdin);
    #endif
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &t);
        if (t == 1) {
            scanf("%d", &k);
            St.insert(k);
            Sk.push(k);
        } else if (t == 2) {
            St.erase(St.find(Sk.top()));
            Sk.pop();
        } else {
            printf("%d\n", *St.rbegin());
        }
    }
}

单调栈大法(官方题解)

#include <iostream>
#include <vector>
#include <cstring>
#include <stack>

using namespace std;

int main()
{
    stack<pair<int,int> > ele, maxi;
    int n, i = 1;
    cin>>n;
    while(i <= n)
    {
        int t, v;
        pair<int, int> p1, p2;
        cin>>t;
        if(t == 1)
        {
            cin>>v;
            ele.push(make_pair(v, i));
            if(maxi.size() == 0)
            {
                maxi.push(make_pair(v, i));
            }
            else
            {
                p1 = maxi.top();
                if(p1.first < v)
                {
                    maxi.push(make_pair(v, i));
                }
            }
        }
        else if(t == 2)
        {
            p1 = ele.top();
            ele.pop();
            p2 = maxi.top();
            if(p1.first == p2.first && p1.second == p2.second)
            {
                maxi.pop();
            }
        }
        else
        {
            p1 = maxi.top();
            cout<<p1.first<<endl;
        }
        i++;
    }
    return 0;
}

C. Balanced Brackets

#include <bits/stdc++.h>
using namespace std;
char s[2000];
int T;
map<char, char> mp;

bool check() {
    stack<char> Sk;
    int n = strlen(s);
    for (int i = 0; i < n; ++i) {
        if (mp.count(s[i])) {
            if (!Sk.empty() && Sk.top() == mp[s[i]]) Sk.pop();
            else return false;
        } else Sk.push(s[i]);
    }
    if (Sk.empty()) return true;
    return false;
}

int main() {
    mp[')'] = '('; mp['}'] = '{'; mp[']'] = '[';
    #ifdef zerol
    freopen("in", "r", stdin);
    #endif
    scanf("%d", &T);
    while(T--) {
        scanf("%s", s);
        if (check()) puts("YES");
        else puts("NO");
    }
}

D. 向右看齐

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1E6 + 100;
int n, a[maxn], ans[maxn];
stack<int> S;

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
    for (int i = n - 1; i >= 0; --i) {
        while (!S.empty() && a[S.top()] <= a[i]) S.pop();
        if (S.empty()) ans[i] = -1;
        else ans[i] = S.top();
        S.push(i);
    }
    for (int i = 0; i < n; ++i)
        printf("%d\n", ans[i] + 1);
}

E. 锯栅栏

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, k;
LL ans;
priority_queue<LL, vector<LL>, greater<LL>> pq;

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &k);
        pq.push(k);
    }
    if (n != 1)
        while (1) {
            LL t = pq.top(); pq.pop();
            t += pq.top(); pq.pop();
            ans += t;
            if (pq.empty()) break;
            pq.push(t);
        }
    printf("%lld\n", ans);
}

G. 都市地平线

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 1e14 + 7;

struct Node {
    int x, h;
    int type;
    bool operator < (const Node &u) const {
        return x < u.x;
    }
};

int n;
Node a[100000];

int main() {
    #ifdef ULTMASTER
    freopen("a.in", "r", stdin);
    // freopen("a.out", "w", stdout);
    #endif
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        a[2 * i] = (Node){x, z, 1};
        a[2 * i + 1] = (Node){y, z, 0};
    }
    sort(a, a + 2 * n);
    multiset<int> ms;
    ll ans = 0;
    // for (int i = 0; i < 2 * n; ++i)
    //     printf("%d %d\n", i, a[i].x);
    for (int i = 0; i < 2 * n; ++i) {
        if (!ms.empty()) {
            // printf("%d %d %d %d %d\n", i, a[i].x, a[i-1].x, *ms.rbegin(), ms.size());
            ans += 1LL * (a[i].x - a[i - 1].x) * (*ms.rbegin());
        }
        if (a[i].type == 1)
            ms.insert(a[i].h);
        else
            ms.erase(ms.find(a[i].h));
    }
    printf("%lld\n", ans);
    return 0;
}

Comments