滑动窗口的作用:
1.求一个数组arr[n]中 每个固定长度为m的连续区间的最大值/最小值,复杂度O(n)
2.求一列数 a1 a2 .... an 从左到右,最大值变化的次数,比如 4 1 5 10 7 9 ,变化次数为 3 (4-->5--->10)
用双端队列就可以完成,把数组变量放全局位置,不然可能会报 RuntimeError 栈溢出。
没接触过这个算法,不会做,哎,还是好好加油吧。
//滑动窗口
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1e7+10;
int t;
ll arr[maxn];
ll dq[maxn];
ll n,m,k,p,q,r,mod;
ll front,back;
ll A,B;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mod);
for(int i=1;i<=k;i++)
{
scanf("%lld",&arr[i]);
}
for(int i=k+1;i<=n;i++)
{
arr[i] = (p*arr[i-1] + q*i + r)%mod;
}
//滑口大小m
A = B = 0;
front = back = 0;
ll j = n-m+1;
for(ll i=n;i>j;i--)
{
while(back>front && arr[dq[back-1]]<=arr[i]) back--;
dq[back++] = i;
}
for(ll i=j;i>=1;i--)
{
while(back>front && arr[dq[back-1]]<=arr[i]) back--;
dq[back++] = i;
//到了
A = A + (arr[dq[front]] ^ (i));
B = B + ((back-front) ^ (i));
if(dq[front]>=i+m-1)
{
front++;
}
}
printf("%lld %lld\n",A,B);
}
return 0;
}//3853MS C++