Loading

暑期训练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);
}

 

posted @ 2020-08-19 20:07  MQFLLY  阅读(193)  评论(0编辑  收藏  举报