Editorial for Stonk


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Nhận xét rằng, nếu số cổ phiếu của một cổ đông là hằng số ~c~ trong quá trình công ty thu về các cổ tức thì số tiền mà cổ đông thu về sẽ là ~c \times \text{(tổng giá trị cổ tức)}~. Do đó, với mỗi cổ đông, ta chỉ cần cập nhật tổng lợi nhuận mỗi khi số cổ phiếu của cổ đông có thay đổi (truy vấn loại ~1~) hoặc khi cần cho biết lợi nhuận hiện tại của cổ đông (truy vấn loại ~3~).

Về chi tiết cài đặt, ta cần lưu lại các giá trị sau:

  • acc_profit[p]: Tổng lợi nhuận chưa được rút của cổ đông ~p~.
  • stock_cnt[p]: Số cổ phiếu hiện tại của cổ đông ~p~.
  • stock_price_index[p]: Tổng cổ tức công ty thu về được tính đến lần cập nhật cuối cùng của cổ đông ~p~.
  • acc_stock_price: Tổng cổ tức cho đến truy vấn hiện tại.

Khi đó, với mỗi truy vấn ~1~ hoặc ~3~, ta cần cập nhật tổng lợi nhuận cho cổ đông ~p~ thêm một lượng bằng ~\texttt{stock_cnt[p]} \times (\texttt{acc_stock_price} - \texttt{stock_price_index[p]})~, rồi cập nhật lại các biến stock_cnt[p]stock_price_index[p] một cách tương ứng.

Độ phức tạp: ~O(n + q)~

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

using u64 = unsigned long long;
const u64 MOD = 1'000'000'007;

int main() {
    cin.tie(0)->sync_with_stdio(0);

    int n, q;
    cin >> n >> q;
    vector<u64> stock_cnt(n), acc_profit(n), stock_price_index(n);
    u64 acc_stock_price = 0;

    auto realize_profit = [&](int p) {
        u64 stock_price = (acc_stock_price - stock_price_index[p]) % MOD;
        stock_price_index[p] = acc_stock_price;

        acc_profit[p] += stock_cnt[p] % MOD * stock_price % MOD;
        acc_profit[p] %= MOD;
    };

    while (q--) {
        int t;
        cin >> t;
        if (t == 1) {
            int p, x;
            cin >> p >> x;
            --p;
            realize_profit(p);
            stock_cnt[p] += x;
        } else if (t == 2) {
            int v;
            cin >> v;
            acc_stock_price += v;
        } else if (t == 3) {
            int p;
            cin >> p;
            --p;
            realize_profit(p);
            cout << exchange(acc_profit[p], 0) << '\n';
        }
    }

    return 0;
}

Comments

Please read the guidelines before commenting.


There are no comments at the moment.