【單調棧】【CF5E】 Bindian Signalizing
阿新 • • 發佈:2018-11-10
Description
給你一個環,環上有一些點,點有點權。定義環上兩點能相互看見當且僅當兩點間存在一個弧使得弧上不存在一個點的點權大於著兩個點。求一共有多少個點能互相看到
Input
第一行 一個整數\(n\)代表環上點的個數
第二行\(n\)個數代表環上每個點的點權
Output
一個數代表答案
Hint
\(For~All:\)
\(3~\leq~n~\leq~10^6\)
Solution
考慮到兩個點的貢獻只會被計算一次,我們不妨令權值較小的點貢獻答案。
先考慮在鏈上怎麼做
顯然對於點\(i\),點\(j\)能對他貢獻答案的必要條件是\(i\)到\(j\)
考慮在環上的做法。
發現如果把最大的點提到前面,那麼計算出的答案顯然除了最大的點以外都是合法的。考慮對最大的點,缺少的答案是最大點前面的字尾最大值。於是就從鏈尾向鏈頭掃一遍,加上字尾最大值。需要注意的是如果一個點已經作為之前的字尾max貢獻了答案的話,那麼這個點的貢獻就不能計算了。
Code
#include<cstdio> #define rg register #define ci const int #define cl const long long int typedef long long int ll; namespace IO { char buf[90]; } template<typename T> inline void qr(T &x) { char ch=getchar(),lst=' '; while(ch>'9'||ch<'0') lst=ch,ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(lst=='-') x=-x; } template<typename T> inline void qw(T x,const char aft,const bool pt) { if(x<0) x=-x,putchar('-'); int top=0; do { IO::buf[++top]=x%10+'0'; x/=10; } while(x); while(top) putchar(IO::buf[top--]); if(pt) putchar(aft); } template<typename T> inline T mmax(const T a,const T b) {return a > b ? a : b;} template<typename T> inline T mmin(const T a,const T b) {return a < b ? a : b;} template<typename T> inline T mabs(const T a) {return a < 0 ? -a : a;} template<typename T> inline void mswap(T &a,T &b) { T temp=a;a=b;b=temp; } const int maxn = 1000010; struct M { int a,b; }; M stack[maxn]; int n,top; int MU[maxn],CU[maxn]; bool used[maxn]; int main() { qr(n); for(rg int i=1;i<=n;++i) qr(MU[i]); rg int mx=0; for(rg int i=1;i<=n;++i) if(MU[i] > MU[mx]) mx=i; for(rg int i=mx;i<=n;++i) CU[++top]=MU[i]; for(rg int i=1;i<mx;++i) CU[++top]=MU[i]; mx=0; rg ll ans=0; stack[top=1]=(M){CU[1],1}; for(rg int i=2;i<=n;++i) { while(top && (stack[top].a < CU[i])) ans+=stack[top--].b; if(stack[top].a == CU[i]) ans+=(stack[top].b++)+(top > 1); else {stack[++top]=(M){CU[i],1}; ++ans;} } mx=0;for(rg int i=2;i<=n;++i) if(CU[i] >= mx) {mx=CU[i];used[i]=true;} mx=0;for(rg int i=n;i>1;--i) if(CU[i] >= mx) {if(!used[i]) ++ans;mx=CU[i];} qw(ans,'\n',true); return 0; }