CF5E-Bindian Signalizing【单调栈】
生活随笔
收集整理的這篇文章主要介紹了
CF5E-Bindian Signalizing【单调栈】
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/CF5E
題目大意
圓上有nnn個(gè)山,兩個(gè)山之間可以看到當(dāng)且僅當(dāng)它們之間的兩條弧中有一條滿(mǎn)足所有山都不高于它們兩個(gè)。
求可以看到的山的對(duì)數(shù)。
3≤n≤106,1≤hi≤1093\leq n\leq 10^6,1\leq h_i\leq 10^93≤n≤106,1≤hi?≤109
解題思路
先找到最高的山,然后先考慮它之外的點(diǎn)對(duì)再考慮這座山的貢獻(xiàn),因?yàn)檫@樣矮的點(diǎn)之間肯定有一座高山擋著。
然后前后各維護(hù)一個(gè)單調(diào)隊(duì)列,每個(gè)元素被彈出的時(shí)候就會(huì)統(tǒng)計(jì)一個(gè)點(diǎn)對(duì)。
然后考慮相同的情況,對(duì)于前后中的一個(gè)做的時(shí)候,彈完之后在單調(diào)隊(duì)列上二分相同的位置即可。
時(shí)間復(fù)雜度O(nlog?n)O(n\log n)O(nlogn)
code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e6+10; int n,m,mx,top,a[N],b[N],s[N],v[N]; long long ans; int main() {scanf("%d",&m);mx=1;for(int i=1;i<=m;i++){scanf("%d",&b[i]);if(b[i]>b[mx])mx=i;}for(int i=mx+1;i<=m;i++)a[++n]=b[i];for(int i=1;i<mx;i++)a[++n]=b[i];for(int i=1;i<=n;i++){while(top>0&&a[s[top]]<a[i])top--,ans++;int l=1,r=top;while(l<=r){int mid=(l+r)>>1;if(a[s[mid]]==a[i])r=mid-1;else l=mid+1;}ans+=top-r;s[++top]=i;}top=0;for(int i=n;i>=1;i--){while(top>0&&a[s[top]]<a[i])top--,ans++;s[++top]=i;}for(int i=1,z=0;i<=n;i++)if(a[i]>=z)z=a[i],ans+=!v[i],v[i]=1;for(int i=n,z=0;i>=1;i--)if(a[i]>=z)z=a[i],ans+=!v[i],v[i]=1;printf("%lld\n",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的CF5E-Bindian Signalizing【单调栈】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ps怎么做撕裂字(ps怎么做撕裂字体)
- 下一篇: CF11D-A Simple Task【