杭电多校第三次 Problem A. Ascending Rating(单调队列)
【题意】
给你一个长为n的数组a
让你对于每个长度为m的窗口。
算出其中的最大值以及从左往右遍历的时候这个最大值更新的次数。
【题解】
单调队列。
从后往前滑动窗口。
会发现我们维护以这个窗口里面的值为元素的单调队列的时候。
这个单调队列的长度就是最大值更新的次数。
因为我们把a[i]加入队列的时候。
队列尾巴上,小于等于这个a[i]的元素都会被删掉.
每个都这么做的话。
队列里面的元素就和更新时候的元素对应。
最大值就是队列的头部。
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define pii pair<ll,ll>
using namespace std;
const int maxn=10000005;
ll nex[maxn],a[maxn],qq[maxn],t;
ll p,q,r,mo,ans,cnt,j,ctt,n,m,k,i,ma,ct,kk;
int main()
{
ll T;
scanf("%lld",&T);
while(T--)
{
i=1;
scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mo);
while(i<=n)
{
if(i<=k) scanf("%lld",&a[i]);
else a[i]=(p*a[i-1]+q*i+r)%mo;
i++;
}
ans=cnt=0;
for(ll h=1,t=0,i=n;i;i--)
{
while(h<=t&&a[qq[t]]<=a[i]) t--;
qq[++t]=i;
if(i<=n-m+1)
{
while(qq[h]>=i+m) h++;
ans+=(i^a[qq[h]]);
cnt+=(i^(t-h+1));
}
}
printf("%lld %lld\n",ans,cnt);
}
return 0;
}