欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

G. Gentle Jena(单调栈) 2020 年 “联想杯”全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛

程序员文章站 2022-07-08 16:43:27
...

G. Gentle Jena(单调栈) 2020 年 “联想杯”全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛

G. Gentle Jena(单调栈) 2020 年 “联想杯”全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛

题意:
给出b[i]的计算公式,第i回合加上b[i]这个数,第i回合的结果为所有区间最小值的和。求所有回合结果的异或值。

思路:
维护一个递增的单调栈,保证弹出的数都比b[i]大,那么这些数在包含b[i]的区间里面都不会被计算到。

单调栈里面维护这个数的值,以这个数为右端点的区间最小值和,下标。

#include <ctime>
#include <iostream>
#include <assert.h>
#include <vector>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long ll;

const int mod = 998244353;
const int maxn = 1e7 + 7;
ll b[maxn],ans[maxn];

struct Node {
    ll val,sum;
    int id;
}stk[maxn];

int main() {
    ll n,p,x,y,z;scanf("%lld%lld%lld%lld%lld%lld",&n,&p,&x,&y,&z,&b[1]);
    int top = 1;
    stk[1] = {b[1],b[1],1};
    ll sum = b[1];
    ans[1] = b[1];
    for(int i = 2;i <= n;i++) {
        b[i] = (x * ans[i - 1] % p + y * b[i - 1] % p + z) % p; //递增单调队列
        sum = (sum + b[i]) % p;
        ll tmp = 0;
        int id = 0;
        while(top && stk[top].val > b[i]) {
            top--;
        }
        tmp = stk[top].sum + (i - stk[top].id) * b[i];
        stk[++top] = {b[i],tmp,i};
        ans[i] = (ans[i - 1] + tmp) % mod;
    }
    
    ll res = 0;
    for(int i = 1;i <= n;i++) {
        res = res ^ ans[i];
    }
    printf("%lld\n",res);
    return 0;
}