1. 程式人生 > >51nod 1215 數組的寬度&poj 2796 Feel Good(單調棧)

51nod 1215 數組的寬度&poj 2796 Feel Good(單調棧)

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>
#define
ll 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; }
View Code

  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(單調棧)