链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6319
思路:
单调队列倒着维护,队列里面剩下的值的数量就是这一段区间的count值,如样例第一个区间:3 2 2 1 5 7
单调队列倒着维护遍历一遍变成了:7 5 3
长度为3,队首为最大值7
实现代码:
#include<cstdio>
using namespace std;
#define ll long long
const int M = 1e7+;
ll a[M],p,q,r,mod;
ll n,m,k;
ll lis[M],head,tail,t;
int main()
{
scanf("%lld",&t);
while(t--){ scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mod);
for(int i = ;i <= k;i ++)
scanf("%lld",&a[i]);
for(int i = k + ;i <= n;i ++)
a[i] = ((p * a[i - ]) % mod + q * i % mod + r) % mod;
head = tail = ;
for(int i = n;i >= n-m+;i --){
while(head < tail&&a[lis[tail-]] <= a[i]) -- tail;
lis[tail++] = i;
}
ll A = ,B = ;
A += a[lis[head]] ^ (n-m+);
B += (tail - head) ^ (n - m + );
for(int i = n-m;i >= ;i --){
while(lis[head] > i + m - &&head < tail) ++head;
while(head < tail&&a[lis[tail - ]] <= a[i]) --tail;
lis[tail++] = i;
A += a[lis[head]] ^ i;
B += (tail - head) ^ i;
}
printf("%lld %lld\n",A,B);
}
return ;
}