跳过正文
  1. Posts/

蓝桥杯2019国B-第八大奇迹

·473 字·1 分钟· loading
DogDu
作者
DogDu
相信代码的力量,用实现驱动学习
目录

题目传送:P8701 [蓝桥杯 2019 国 B] 第八大奇迹 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题的关键在于“只查询第八大”这一特殊限制。因为查询目标固定,不需要维护整个有序信息,而只需要在每个区间里保留前八大的候选值即可。

思路
#

第一反应当然可以是主席树,但这个题没必要把结构搞得那么重。

更直接的做法,是在线段树每个节点里维护当前区间的前八大值,pushup 时像归并排序那样合并两个有序数组。

代码
#

CPP 代码 · 共 52 行
#include<iostream>
using namespace std;

const int maxn = 1e5 + 10;

struct node {
    int v[8] = {0};
} t[maxn << 2]; // 每个节点记录这个区间的前八大

inline void pushup(node &x, node &l, node &r) // 用归并排序思想合并
{
    int p1 = 0, p2 = 0, p = 0;
    while (p < 8 && p1 < 8 && p2 < 8)
        if (l.v[p1] > r.v[p2]) x.v[p++] = l.v[p1++];
        else x.v[p++] = r.v[p2++];
}

inline void modify(int x, int l, int r, int &dist, int &v) {
    if (l == r) {
        t[x].v[0] = v;
        return;
    }
    int mid = l + r >> 1;
    if (mid >= dist) modify(x << 1, l, mid, dist, v);
    else modify(x << 1 | 1, mid + 1, r, dist, v);
    pushup(t[x], t[x << 1], t[x << 1 | 1]);
}

inline node query(int x, int l, int r, int &L, int &R) {
    if (l >= L && r <= R) return t[x];
    int mid = l + r >> 1;
    node t1, t2, ans;
    if (mid >= L) t1 = query(x << 1, l, mid, L, R);
    if (mid < R) t2 = query(x << 1 | 1, mid + 1, r, L, R);
    pushup(ans, t1, t2);
    return ans;
}

int l, n, x, y;
char op;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> l >> n;
    while (n--) {
        cin >> op >> x >> y;
        if (op == 'C') modify(1, 1, l, x, y);
        else cout << query(1, 1, l, x, y).v[7] << '\n';
    }
    return 0;
}