Second My Problem First HDU - 3706 单调队列

单调队列

单调队列是指一个队列内部的元素具有严格单调性的一种数据结构,分为单调递增队列和单调递减队列。

单调队列满足两个性质

1.单调队列必须满足从队头到队尾的严格单调性。

2.排在队列前面的比排在队列后面的要先进队。

元素进队列的过程对于单调递增队列,对于一个元素a 如果 a > 队尾元素 那么直接将a扔进队列 如果 a <= 队尾元素 则将队尾元素出队列 知道满足 a 大于队尾元素即可;

 

单调栈和这个差不多。但是不管是那个它只有一端可以移动(比如单调队列你只能O(1)时间内获得队列头部元素,对于队列尾部就不一定了),这个时候你可以用stl的双端队列。或者你可以模拟队列嘛

 

题意:

S= Ai%B

T= min{Sk} (i-A<=k<=i)

让你求所有Ti得乘积取模于B的得数

 

题解:

这就只需要维护一个长度为A(有可能还小于A)的单调队列就可以了

 

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 typedef unsigned long long ull;
 9 const int inf=0x3f3f3f3f;
10 const ll INF=0x3f3f3f3f3f3f3f3fll;
11 const int maxn=1e5+5;
12 int main()
13 {
14     ll n,a,b,s,e,que[maxn],sum,ans,pos[maxn];
15     while(~scanf("%lld%lld%lld",&n,&a,&b))
16     {
17         s=e=0;
18         ans=sum=1;
19         for(ll i=1;i<=n;++i)
20         {
21             ans=(ans*a)%b;
22             while(s<e && que[e-1]>ans) e--;
23             que[e]=ans;
24             pos[e++]=i;
25             if(s<e && pos[e-1]-pos[s]>a) s++;
26             sum=(sum*que[s])%b;
27         }
28         printf("%lld\n",sum);
29     }
30     return 0;
31 }

 

posted @ 2020-06-17 16:59  kongbursi  阅读(126)  评论(0编辑  收藏  举报