單調隊列模板鏈接
https://blog.csdn.net/qq_41268947/article/details/81483268
Problem A. Ascending Rating
Problem Description
Before the start of contest, there are ICPC contestants waiting in a long queue. They are labeled by to from left to right. It can be easily found that the -th contestant’s QodeForces rating is .
Little Q, the coach of Quailty Normal University, is bored to just watch them waiting in the queue. He starts to compare the rating of the contestants. He will pick a continous interval with length , say , and then inspect each contestant from left to right. Initially, he will write down two numbers and . Everytime he meets a contestant with strictly higher rating than , he will change to and to .
Little T is also a coach waiting for the contest. He knows Little Q is not good at counting, so he is wondering what are the correct final value of and . Please write a program to figure out the answer.
Input
The first line of the input contains an integer , denoting the number of test cases. In each test case, there are integers in the first line, denoting the number of contestants, the length of interval, and the parameters . In the next line, there are integers , denoting the rating of the first contestants. To reduce the large input, we will use the following generator. The numbers and are given initially. The values are then produced as follows :
Output
Since the output file may be very large, let’s denote and as the result of interval . For each test case, you need to print a single line containing two integers and , where :
Sample Input
1
10 6 10 5 5 5 5
3 2 2 1 5 7 6 8 2 9
Sample Output
46 11
題意
有序列a1~an,對於每個連續的長爲m的子區間[ax,ax+m-1],求兩個值:maxrating和count,兩者初始值均爲0,從左到右掃描每個元素,如果有元素大於maxrating,則更新maxrating且讓count++。求出每個區間的maxrating和count後,再按題給公式求出A和B。
思路
這道題運用單調隊列,但是我們不能從首到尾判斷,因爲單調隊列只能存每個區間的最大值,但count求的是最大值更新了多少次,那麼,區間變換了,count值也會不同。還有就是如果遇到那種最小值不在該區域內,需要隊首後移這時也需要重算count
所以倒過來,從尾到首進行單調隊列
代碼
#include<cstdio>
const int N=10000010;
int i,a[N],v[N],h,t; //v是單調隊列,h是隊首,t是隊尾
long long A,B;
int main()
{
int T,n,m,k,p,q,r,mod;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d%d%d%d",&n,&m,&k,&p,&q,&r,&mod);
for(i=1;i<=k;i++)
scanf("%d",&a[i]);
for(i=k+1;i<=n;i++)
a[i]=(1LL*p*a[i-1]+1LL*q*i+r)%mod;
A=0,B=0;
h=1,t=0;
for(i=n;i;i--)
{
while(h<=t&&a[v[t]]<=a[i]) t--;
//隊列遞減所以隊尾上小於要插入值的元素都刪除
v[++t]=i;
if(i+m-1<=n)//i可以作爲區間起點了
{
while(v[h]>=i+m) h++;//去掉區間外的元素
A+=i^a[v[h]];
B+=i^(t-h+1);
}
}
printf("%lld %lld\n",A,B);
}
return 0;
}