Codeforces Round #457 (Div. 2) D. Jamie and To-do List 主席树

Posted kaka0010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #457 (Div. 2) D. Jamie and To-do List 主席树相关的知识,希望对你有一定的参考价值。

原题链接:https://codeforces.ml/contest/916/problem/D

题意

有四个操作

  1. set 将x的优先级修改为y
  2. remove 将x这个数移除
  3. query 查询有多少数小于x的优先级
  4. undo 撤销x次操作

分析

看到撤销操作应该就知道这是个主席树的题了,但撤销时需要维护两个信息,一个是相同优先级的数有几个,还有一个是当前这个数的优先级是多少,因此必须建两颗主席树,别的操作按照题意来就可以了,比较基础的主席树练习。太久没写主席了,手写错了一遍 ,下次还是得小心。

Code

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<ll, ll> PII;
typedef unsigned long long ull;
const int N = 1e5 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9+7;

int rt1[N * 100], rt2[N * 100], sum[N * 100], ls[N * 100], rs[N * 100], cnt;
void modify(int &now, int pre, int l, int r, int pos, int val) {
    now = ++cnt;
    ls[now] = ls[pre], rs[now] = rs[pre], sum[now] = sum[pre] + val;
    if (l == r) return;
    int mid = (l + r) >> 1;
    if (pos <= mid) modify(ls[now], ls[pre], l, mid, pos, val);
    else modify(rs[now], rs[pre], mid+1, r, pos, val);
}
int query(int now, int l, int r, int ql, int qr) {
    if (ql <= l && qr >= r) return sum[now];
    int mid = (l + r) >> 1;
    int ans = 0;
    if (ql <= mid) ans += query(ls[now], l, mid, ql, qr);
    if (qr > mid) ans += query(rs[now], mid+1, r, ql, qr);
    return ans;
}
map<string, int> id;
int tot;
int getid(string s) {
    if (id.find(s) == id.end()) {
        id[s] = ++tot;
        return tot;
    }
    else return id[s];
}
void solve() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        string opt, name; int priority;
        cin >> opt;
        rt1[i] = rt1[i-1], rt2[i] = rt2[i-1];
        if (opt == "set") {
            cin >> name >> priority;
            int x = getid(name);
            int pre = query(rt2[i], 1, MOD, x, x);
            if (!pre) {
                modify(rt2[i], rt2[i], 1, MOD, x, priority);
                modify(rt1[i], rt1[i], 1, MOD, priority, 1);
            } else {
                modify(rt2[i], rt2[i], 1, MOD, x, -pre+priority);
                modify(rt1[i], rt1[i], 1, MOD, pre, -1);
                modify(rt1[i], rt1[i], 1, MOD, priority, 1);
            }
        } else if (opt == "query") {
            cin >> name;
            int x = getid(name);
            priority = query(rt2[i], 1, MOD, x, x);
            if (!priority) cout << -1 << endl;
            else if (priority == 1) cout << 0 << endl;
            else cout << query(rt1[i], 1, MOD, 1, priority-1) << endl;
            fflush(stdout);
        } else if (opt == "remove") {
            cin >> name;
            int x = getid(name);
            priority = query(rt2[i], 1, MOD, x, x);
            if (!priority) continue;
            modify(rt2[i], rt2[i], 1, MOD, x, -priority);
            modify(rt1[i], rt1[i], 1, MOD, priority, -1);
        } else if (opt == "undo") {
            int x; cin >> x;
            rt1[i] = rt1[i-x-1], rt2[i] = rt2[i-x-1];
        }
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif
    solve();
    return 0;
}

以上是关于Codeforces Round #457 (Div. 2) D. Jamie and To-do List 主席树的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #457 (Div. 2) CJamie and Interesting Graph

Codeforces Round #457 (Div. 2) A Jamie and Alarm Snooze

Codeforces Round #457 (Div. 2) BJamie and Binary Sequence

Codeforces Round #457 (Div. 2) D. Jamie and To-do List 主席树

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)