题目大意:
给你n个数,对于第i个数求区间(i , i+m-1)的最大值以及严格递增序列的长度。
解题思路:
n是1e7,所以肯定是单调队列,但是单调队列注意要倒着维护,倒着维护感觉会比较的简单。最大值直接取 head 即可,长度即tail-head的长度。
Ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+5;
int n,m,k,p,q,r,mod,a[maxn],que[maxn];
int main()
{
int QAQ;
scanf("%d",&QAQ);
while(QAQ--)
{
scanf("%d%d%d%d%d%d%d",&n,&m,&k,&p,&q,&r,&mod);
for(int i=1;i<=n;i++) //处理出n个数
{
if(i<=k) scanf("%d",&a[i]);
else a[i]=(1LL*p*a[i-1]+1LL*q*i+1LL*r)%mod;
}
ll A=0,B=0,mx,cou;
int head=0,tail=0;
for(int i=n;i>=1;i--) //单调队列
{
while(tail>head&&a[que[tail-1]]<=a[i]) tail--; //当尾结点加入时只能比上个结点小
que[tail++]=i;
while((que[head]>i+m-1)&&head<tail) head++; //判断头节点是否合法
if(i<=n-m+1)
{
mx=a[que[head]],cou=tail-head; //统计最大值以及长度 计算答案
A+=(1LL*mx)^(1LL*i);
B+=(1LL*cou)^(1LL*i);
}
}
printf("%lld %lld\n",A,B);
}
}