Problem Description
Before the start of contest, there are t. Please write a program to figure out the answer.
 

 

Input
The first line of the input contains an integer ) are then produced as follows :
D
6.
 

 

Output
Since the output file may be very large, let's denote B, where :
)
'' denotes binary XOR operation.
 

 

Sample Input
1 10 6 10 5 5 5 5
3 2 2 1 5 7 6 8 2 9
 
Sample Output
46 11
 
题意:输入 D  输入k个数,总共有n个数,如果输入不够的话就由上面那个公式把剩下的补齐,然后区间长度为m,访问所有的长度m的区间,
我们要求每个区间的最大值变化次数 (比如 3 2 2 1 5 7        那么我们的最大值3-5-7   所以次数是3,最大值是7) 和最大值     ,然后求每个区间的变化次数和最大值分别异或第几个区间号i的累加和
 
思路:一看复杂度,只有o(n)可以过,那么就去想o(n)算法,乍一看最大值就是用一个滑动窗口可以求出来是o(n)的,但是count我们不好记录,我们可以发现count的那些最大值
其实是一个单调递增的序列,我们想怎么去维护呢,我们求最大值那么肯定就要用o(n)了,我们可不可以同时求呢,说明我的单调序列也要能尽量沿用上一个区间的值,避免遍历
我们可以回想下,求滑动窗口的时候那个队列就是存的一个以队列首为最大值的一个最长单调递减序列,那么我们怎么由递减序列变成递增序列呢,很简单,我们倒着求滑动窗口
到时候队列长度即是最大值的变化次数
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<deque>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m,t,k,p,q,r,mod;
int a[10000001];
deque<ll> qx;
int cnt;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d%d%d%d",&n,&m,&k,&p,&q,&r,&mod);
        qx.clear();
        for(int i=1;i<=k;i++)
            scanf("%d",&a[i]);
        for(int i=k+1;i<=n;i++)
             a[i]=(1ll*p*a[i-1]+1ll*q*i+r)%mod;
        ll x=0,y=0;
        for(int i=n;i>=1;i--)
        {
            while(!qx.empty()&&a[i]>=a[qx.front()])
                 qx.pop_front();
            qx.push_front(i);
            if(i-1<=n-m)
            {
                while(!qx.empty()&&qx.back()>=i+m) qx.pop_back();
                x+=i^a[qx.back()];
                y+=i^qx.size();
            }
        }    
        printf("%lld %lld\n",x,y);
    }
    
}

 

 

相关文章: