Skip to content

11990: 【原1990】二哥听CD

题目

题目描述

author: qujun 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1990

题目描述

二哥有很多CD,每次想听它们的时候都不知道挑哪个好。

为了方便自己选CD,现在二哥给他所有的CD一个整数作为好感度。显然,好感度肯定不是永远不变的,随着时间的变化,某些CD的好感度也会发生变化。

现在给你一个长度为N的整数序列,序列的第i个表示编号为i的CD的初始好感度,这里保证第i张CD的初始好感度大于等于第i-1张的初始好感度。接下来会给你M对整数x和y,表示在第i天编号x的CD好感度会增加y(y为1或-1),你需要求出在每次变化后二哥好感度最低的CD是哪张,如果有多张好感度都是最低的,那么选最后变成这个好感度的CD,在这里我们假设在初始序列中编号i的CD的变化到初始好感度的时间晚于编号i-1的CD变化到其初始好感度的时间。

输入格式

输入共有两行。

第1行两个整数N和M,表示CD数和需要询问的天数。

第2行有n个整数,表示初始好感度。

接下来M行,每行两个整数x,y,表示M次询问。

输出格式

对于每次询问输出这次变化后所求的CD编号。一个询问占一行。

说明

对于30%的数据:\(1 \leq n, m \leq 100\)。 对于60%数据:\(1 \leq n, m \leq 100,000\)。 对于全部数据:任何时刻好感度不会超过有符号32位整数,\(1 \leq n, m \leq 2,000,000\)。

注意:时限比较紧,请仔细估计复杂度,并建议不要使用STL,否则容易超时。

样例输入

3 4
1 2 3
1 1
1 1
2 1
3 -1

样例输出

1
2
2
3

限制

时间限制:2000ms,内存限制:262144kb。

Neight99's solution

#include <iostream>

using namespace std;

const int maxN = 2e6 + 100;

struct Node {
    int id;
    int like;
    int date;
};

int pos[maxN] = {0}, N, M, date = 1;
Node heap[maxN] = {0};

void buildHeap();
void percolateUp(int);
void percolateDown(int);

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> N >> M;
    for (int i = 1; i <= N; i++) {
        cin >> heap[i].like;
        heap[i].id = i;
        heap[i].date = date++;
        pos[i] = i;
    }

    buildHeap();

    int x, y;
    for (int i = 0; i < M; i++) {
        cin >> x >> y;
        heap[pos[x]].like += y;
        heap[pos[x]].date = date++;
        if (y > 0) {
            percolateDown(pos[x]);
        } else if (y < 0) {
            percolateUp(pos[x]);
        }
        cout << heap[1].id << '\n';
    }

    return 0;
}

void buildHeap() {
    for (int i = N / 2; i > 0; i--) {
        percolateDown(i);
    }
}

void percolateUp(int hole) {
    int like = heap[hole].like, id = heap[hole].id, date = heap[hole].date,
        parent;

    while (hole / 2 != 0) {
        parent = hole / 2;
        if (like <= heap[parent].like) {
            heap[hole].like = heap[parent].like;
            heap[hole].id = heap[parent].id;
            heap[hole].date = heap[hole].date;
            pos[heap[hole].id] = hole;
            hole = parent;
        } else {
            break;
        }
    }
    heap[hole].id = id;
    heap[hole].like = like;
    heap[hole].date = date;
    pos[id] = hole;
}

void percolateDown(int hole) {
    int like = heap[hole].like, id = heap[hole].id, data = heap[hole].date,
        child;

    while ((hole * 2) <= N) {
        child = hole * 2;
        if (child < N) {
            if (heap[child + 1].like < heap[child].like ||
                (heap[child + 1].like == heap[child].like &&
                 heap[child + 1].date > heap[child].date)) {
                child += 1;
            }
        }
        if (like > heap[child].like ||
            (like == heap[child].like && date < heap[child].date)) {
            heap[hole].like = heap[child].like;
            heap[hole].id = heap[child].id;
            heap[hole].date = heap[child].date;
            pos[heap[hole].id] = hole;
            hole = child;
        } else {
            break;
        }
    }
    heap[hole].id = id;
    heap[hole].date = date;
    heap[hole].like = like;
    pos[id] = hole;
}

yyong119's solution

#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAX_N 2000010
using namespace std;
int n, m, cur_time;
int cd_seq[MAX_N], id_map[MAX_N], pos_map[MAX_N], time_seq[MAX_N];
inline int read() {
    char ch = getchar(); int res = 0, flag = 1;
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') flag = -1, ch = getchar();
    while (ch >= '0' && ch <= '9')
        res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
    return res * flag;
}
inline void swap_element(int x, int y) {
    swap(cd_seq[x], cd_seq[y]);
    swap(id_map[x], id_map[y]);
    pos_map[id_map[x]] = x;
    pos_map[id_map[y]] = y;
}
inline bool cmp(const int &x, const int &y) {
    return (cd_seq[x] == cd_seq[y] ? time_seq[id_map[x]] > time_seq[id_map[y]] : cd_seq[x] < cd_seq[y]);
}
void push_down(int x) {
    for (register int k = x; (k << 1) <= n;) {
        int min_id = k, l = k << 1, r = k << 1 | 1;
        // left child
        if (cmp(l, min_id)) min_id = l;
        // right child
        if (r <= n && cmp(r, min_id)) min_id = r;
        // check to push down
        if (min_id == k) return;
        swap_element(k, min_id);
        k = min_id;
    }
}
void push_up(int x) {
    for (register int k = x; k > 1;) {
        // parent
        int p = k >> 1;
        // chekc to push up
        if (cmp(k, p)) {
            swap_element(k, p);
            k = p;
        }
        else return;
    }
}
int main() {
    n = read(), m = read();
    for (register int i = 1; i <= n; ++i) {
        cd_seq[i] = read();
        id_map[i] = pos_map[i] = i;
        time_seq[i] = ++cur_time;
    }
    for (register int i = (n >> 1); i > 0; --i)
        push_down(i);
    for (register int i = 0; i < m; ++i) {
        int x = read(), diff = read();
        time_seq[x] = ++cur_time;
        if (diff == 1) {
            ++cd_seq[pos_map[x]];
            push_down(pos_map[x]);
        }
        else {
            --cd_seq[pos_map[x]];
            push_up(pos_map[x]);
        }
        printf("%d\n", id_map[1]);
    }
    return 0;
}