题目大意,就是给你一个序列,在序列中对于每一个长度为m的区间,求区间最大和 每次递增的取区间内数的个数,然后求一个 最大值与i的异或和 和个数与i的异或和

题目分析,我们倒过来用一个递减的单调队列,那么队列中的数,很显然就是正的时候我们需要的递增的数,队列长度即为cnt,队首元素即为最大值,每次当队首的位置不在区间,就出队,维护一个单调队列即可

#include <bits/stdc++.h>
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
int T;
typedef long long ll;
int n,m,k,p,q,r,mod;
const int maxn=1e7+50;
int a[maxn];
//int que[maxn];
struct node
{
    int id;
    int num;
}que[maxn];
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]=((ll)p*a[i-1]%mod+(ll)q*i%mod+r)%mod;
        }
        ll pre=1,cnt=1;
        ll ax=0,bx=0;
        for(int i=n;i>=1;i--)
        {

            while(a[i]>=que[cnt-1].num&&cnt>pre)
            {
                cnt--;
            }
            node tmp;
            tmp.id=i;
            tmp.num=a[i];
            que[cnt++]=tmp;
            if(i<=n-m+1) {
            ax = ax+(que[pre].num^i);
            bx = bx +((cnt-pre)^i);

            }
            if(i<=n-m+1&&cnt!=pre){
                int p =i+m-1;
                if(que[pre].id==p)pre++;
            }
        }
        printf("%lld %lld\n",ax,bx);
    }
    return 0;
}