51nod 1215 數組的寬度&poj 2796 Feel Good(單調棧)
阿新 • • 發佈:2017-08-16
close queue fin click nod stream ++ std tchar
單調棧求每個數在哪些區間是最值的經典操作。
把數一個一個丟進單調棧,彈出的時候[st[top-1]+1,i-1]這段區間就是彈出的數為最值的區間。
poj2796 彈出的時候更新答案即可
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #include<map> #defineView Codell long long using namespace std; const int maxn=500010,inf=1e9; int n,top,ansl,ansr; ll ans=-1; int st[maxn],a[maxn]; ll sum[maxn]; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar(); k*=f; } int main() { read(n); for(int i=1;i<=n;i++)read(a[i]),sum[i]=sum[i-1]+a[i];a[++n]=-1; for(int i=1;i<=n;i++) { for(;top&&a[i]<=a[st[top]];top--) { ll val=1ll*a[st[top]]*(sum[i-1]-sum[st[top-1]]);if(val>ans)ans=val,ansl=st[top-1]+1,ansr=i-1; } st[++top]=i; } printf("%lld\n%d %d",ans,ansl,ansr); return 0; }
51nod1215 求出最大值對答案的貢獻之和與最小值對答案的貢獻之和相減即可。
顯然貢獻為a[i]*(i-st[top])*(st1[top]-st[top-1]);
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #include<map> #define ll long long using namespace std; const int maxn=500010,inf=1e9; int n,top1,top2; int a[maxn],b[maxn],st1[maxn],st2[maxn]; ll mx,mn; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar(); k*=f; } int main() { read(n); for(int i=1;i<=n;i++)read(a[i]),b[i]=a[i];b[++n]=inf; for(int i=1;i<=n;i++) { for(;top1&&a[i]<=a[st1[top1]];top1--) mn+=1ll*a[st1[top1]]*(i-st1[top1])*(st1[top1]-st1[top1-1]); for(;top2&&b[i]>=b[st2[top2]];top2--) mx+=1ll*b[st2[top2]]*(i-st2[top2])*(st2[top2]-st2[top2-1]); st1[++top1]=st2[++top2]=i; } printf("%lld\n",mx-mn); return 0; }View Code
51nod 1215 數組的寬度&poj 2796 Feel Good(單調棧)