题意:输入7个整数 n,m,k,p,q,r,MOD
n:一共有n个数;m:每个区间的长度;k:输入k个数;
p,q,r,MOD:公式要用到的参数
然后求A和B
A:第 i 个区间的最大值( ansA[i] ) 与 i 的异或的结果的和
B:第 i 个区间里上升序列元素个数( ansB[i] ) 与 i 异或的结果的和
思路:
1:因为一共有n个数但是只输入了k个数 所以我们先用题目给的公式把n个数补齐 在补齐的时候记得mod一下
2:因为单调序列维护的是下降序列 而题目要的是上升序列 所以我们倒过来使用单调队列 然后每次队列内的剩余元素个数就是count( ansB[i] )
#include <bits/stdc++.h>
#define ll long long
#define MAXN 10000005
using namespace std;
int n,m,k,p,q,r,mod;
int num[MAXN];//存数
int Q[MAXN];//存点坐标
int head, rear;
//ansA[MAXN]存每个区间的maxrating
//ansB[MAXN]存每个区间的count
int ansA[MAXN],ansB[MAXN];
ll a,b;
int solve() {
int head = rear = 0;
for(int i = n; i > 0; i--) {
while(rear > head && num[Q[rear - 1]] <= num[i]) {
rear--;
}
Q[rear++] = i;
if(i <= n - m + 1){
while(Q[head] >= i + m){
head++;
}
ansA[i] = num[Q[head]];
ansB[i] = rear - head;
}
}
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d%d%d%d%d%d%d",&n,&m,&k,&p,&q,&r,&mod);
for(int i = 1; i <= k; i++) {
scanf("%d",&num[i]);
}
for(int i = k+1; i <= n; i++) {
num[i] = ((ll)p%mod*num[i-1] + (ll)q%mod*i%mod + r%mod)%mod;
}
solve();
a = 0, b = 0;
for(int i = 1;i <= n - m + 1;i++){
a += (ll)ansA[i] ^ i;
b += (ll)ansB[i] ^ i;
}
printf("%lld %lld\n",a,b);
}
}