1. 程式人生 > 實用技巧 >暑期訓練1 Gym - 102623G Gentle Jena 單調棧

暑期訓練1 Gym - 102623G Gentle Jena 單調棧

動態往序列末尾加數字,每次新增完求序列內所有子區間的RMQ(最小值)之和,強制線上求法,求線性做法。

1.考慮某位置上的數x作為區間最小值出現的次數,一旦插入了一個比x大的數,x的貢獻就不再變化。

2.當插入一個數時,只有從末尾往前單調遞增的數的貢獻才會變化,容易想到用一個單調棧維護。

首先,如果這個數已經被彈出棧了,那麼不需要考慮;

而對於棧內的數字,假設它的下標為xi,而它下面的一個數的下標為x i -1,那麼根據單調棧的性質,在xi - x i -1中不存在比當前數更小的數,因此每次新加入一個數時

以[xi - 1, xi ]中任意一個數為區間起點,都可以以新數為區間終點構成新的區間,因此它的貢獻值會增加。


struct ST {
    ll val;
    int idx;
};

ST st[10000005];
int n;
ll x, y, z, p, b;
ll res, pre;

int main() {
    n = readint();
    p = readll();
    x = readll();
    y = readll();
    z = readll();
    b = readll();
    ll now = 0;
    int top = 0;
    for (int i = 1; i <= n; i++) {
        while (top > 0
&& b < st[top].val) { pre = (pre - st[top].val * (st[top].idx - st[top - 1].idx) % MOD + MOD) % MOD; top--; } now += b * (i - st[top].idx) % MOD + pre, now %= MOD; res ^= now; pre += b * (i - st[top].idx) % MOD; pre %= MOD; st[
++top].val = b; st[top].idx = i; b = (x * now + y * b + z) % p; } Put(res); }