Codeforces Round #700 (Div. 2) D(贪心)

题目链接:

D1. Painting the Array I

D2. Painting the Array II

经历这场 \(cf\) 我才意识到操作系统课上看似很简单的最佳页面置换算法并没有那么容易被想到。

题意:给定一个长度为 \(n\) 的数组 \(a_1, a_2,\cdots,a_n(1\le a_i\le n)\) ,将其分为两个不相交的子序列 \(s\)\(t\) ,求 \(seg(s)+seg(t)\) 的最大/最小值。其中 \(seg(c)\) 代表序列 \(c\) 合并相邻的相同元素后的元素个数,例如 \(seg([1,2,2,3,3,3,2])=4\)

上述问题等价于:有一个虚存系统,某进程占用 \(2\) 个内存块,开始时内存为空,依次访问页号 \(a_1,a_2,\cdots,a_n\) ,求最大/最小缺页次数。(这里的最大缺页次数是指即使某一个内存块能匹配也要让其强行缺页,只有两个内存块均命中时才视为命中)。

最小缺页次数即为采用最佳页面置换算法的缺页次数,每次将未来最久不使用的页面替换出去。

最大缺页次数解法与之相对,当前访问页面与两个内存块中页面均不同时,选择将未来最早使用的页面替换出去。

下面两份代码仅 \(29\) 行的 for 循环不同。

\(D1\) \(AC\) 代码:

/**
 * Codeforces Round #700 (Div. 2)
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e5+5;
int a[N], nxt[N];  // nxt[i]代表值为a[i]的下一个位置
void solve()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", a+i);
    }
    vector<int> pos(n+1, n+1);
    for (int i = n; i; --i) {
        nxt[i] = pos[ a[i] ];
        pos[ a[i] ] = i;
        //cout << nxt[i] << ' ';
    }
    //cout << endl;
    nxt[0] = n+1;
    int x = 0, y = 0;
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (a[i] == a[x] || a[i] == a[y]) {ans += x!=y; x=y=i; continue;}
        ++ans;
        if (nxt[x] < nxt[y]) x = i;
        else y = i;
        //cout << a[x] << ' ' << a[y] << endl;
    }
    printf("%d\n", ans);
}

int main()
{
    // ios::sync_with_stdio(0); cin.tie(0);
    int t = 1;
    // scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}

\(D2\) \(AC\) 代码:

/**
 * Codeforces Round #700 (Div. 2)
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e5+5;
int a[N], nxt[N];  // nxt[i]代表值为a[i]的下一个位置
void solve()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", a+i);
    }
    vector<int> pos(n+1, n+1);
    for (int i = n; i; --i) {
        nxt[i] = pos[ a[i] ];
        pos[ a[i] ] = i;
        //cout << nxt[i] << ' ';
    }
    //cout << endl;
    nxt[0] = n+1;
    int x = 0, y = 0;
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (a[i] == a[x]) {x=i; continue;}
        if (a[i] == a[y]) {y=i; continue;}
        ++ans;
        if (nxt[x] > nxt[y]) x = i;
        else y = i;
        //cout << a[x] << ' ' << a[y] << endl;
    }
    printf("%d\n", ans);
}

int main()
{
    // ios::sync_with_stdio(0); cin.tie(0);
    int t = 1;
    // scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}

posted @ 2021-02-08 14:30  Zewbie  阅读(174)  评论(0)    收藏  举报