个人理解:单调队列就是单调栈的升级版。单调队列比单调栈只多了个队首元素出队。
ACM-ICPC Asia Phuket Regional Programming Contest 2013 J:
这道题感觉什么树套树啊,按权值建线段树啊都是可以得解的,但树套树太慢,按权值建线段树又太难写(我懒,所以不想写)。在看了别人的解题报告后,想了一下,得到了单调栈的做法。感觉真的很优美,因为在栈里的id和其对应的sum都是单调的。
这种题目有两个最优条件,一是大小,二是位置。我觉得只有后加入的满足位置更优时,才能用这种单调栈的做法。比如,如果这道题求的是最大子序列,那就不能用单调栈来做了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdlib> 2 #include <cstdio> 3 #include <algorithm> 4 #include <iostream> 5 #define FOR(i,l,r) for (int i=(l);i<=(r);i++) 6 using namespace std; 7 const int maxn=500000+1; 8 typedef long long LL; 9 10 int n,x; 11 LL sum[maxn]; 12 int sta[maxn]; int pos; 13 int ef(LL d) 14 { 15 int l=1,r=pos,mid; 16 while (l<=r) 17 { 18 mid=l+r>>1; 19 if (sum[sta[mid]]<=d) l=mid+1; 20 else r=mid-1; 21 } 22 return r; 23 } 24 int main(){ 25 for (int T;scanf("%d",&T)!=EOF;) 26 for (int p,ans;T--;) 27 { 28 scanf("%d%d",&n,&x); 29 FOR (i,1,n) scanf("%d",&p),sum[i]=sum[i-1]+p; 30 ans=n+1; sta[pos=1]=0; 31 FOR (i,1,n) 32 { 33 p=ef(sum[i]-x); 34 if (p) ans=min(ans,i-sta[p]); 35 while (pos&&sum[sta[pos]]>=sum[i]) pos--; 36 sta[++pos]=i; 37 } 38 printf("%d ",ans==n+1?-1:ans); 39 } 40 return 0; 41 }