链接: 题目链接
思路:
用单调队列来进行优化,在此复习一下什么是单调队列,单调队列里面存放的是一段区间里面按某种关系排列的单调序列,下面就以单调递减为例进行说明,在往单调队列里面添加元素的时候,如果队列的队尾比添加的元素要小得话,那就把队尾元素弹出,一直到队列为空或者队尾元素大于要添加的元素,再将要添加的元素添加进这个单调队列,原则就是,越晚添加的元素越有用,这样可以在O(n)的时间内求出区间的最大值。
代码:
#include <iostream>
#include <cstdio>
#define LL long long
using namespace std;
const int maxn=1e7+5;
LL n,m,k,p,q,r,MOD;
LL num[maxn]={0};
LL imax[maxn]={0};
LL times[maxn]={0};
LL que[maxn]={0};
void slove()
{
int head,tail;
head=tail=0;
for(int i=n;i>0;i--)
{
while(head<tail&&num[que[tail-1]]<=num[i])
tail--;
que[tail++]=i;
if(i>n-m+1)
continue;
while(que[head]>i+m-1)
head++;
imax[i]=num[que[head]];
times[i]=tail-head;
}
}
int main()
{
int T;
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",&num[i]);
for(int i=k+1;i<=n;i++)
num[i]=(p*num[i-1]+q*i+r)%MOD;
slove();
LL sum1,sum2;
sum1=sum2=0;
for(int i=1;i<=n-m+1;i++)
{
sum1+=(imax[i]^i);
sum2+=(times[i]^i);
}
printf("%lld %lld\n",sum1,sum2);
}
return 0;
}
心得:
好好学算法吧,多接触一些算法,这样做题思路就会宽广,算法不能只接触皮毛,得深入去理解它