数据结构 单调栈 【计算所有区间最大值最小值】

 


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

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

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

ID 是个数(次数) 

#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;
}

————————————————
版权声明:本文为CSDN博主「tomjobs」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tomjobs/article/details/106450135

posted @ 2021-04-15 20:00  旅玖旅玖  阅读(403)  评论(0编辑  收藏  举报