题意:长度为n的序列a.对每个m大小的区间[i,i+m-1],求出该区间的最大值,以及最大值变化的次数.
例如区间(4,2,7,5),最大值变化次数为2. n<=1e7.
n<=1e7. 标准解应该为O(n). 容易想到用单调队列维护每个区间的最大值.
发现正着做单调队列的过程中,单调队列的大小 是从右往左数 最大值的变化次数.
例如区间(4,2,7,5,1,3) 单调队列中存的为(7,5,3) 因为每次加入一个数 会把前面比它小的弹出.
那么逆着做一遍单调队列即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+5;
int n,m,k,p,q,r,mod,T,a[N];
int deq[N],front,tail;
int main(){
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",&a[i]);
for(int i=k+1;i<=n;i++) a[i]=(1ll*a[i-1]*p+1ll*q*i+r)%mod;
ll A=0,B=0,tail=0,front=0;
for(int i=n;i>=1;i--){
while(front<tail && deq[front]>i+m-1) front++;
while(front<tail && a[deq[tail-1]]<=a[i]) tail--;
deq[tail++]=i;
if(i>n-m+1) continue;
int mx=a[deq[front]],cnt=tail-front;
A=A+(mx^i),B=B+(cnt^i);
}
printf("%I64d %I64d\n",A,B);
}
return 0;
}