【单调栈】zjoj p1859子序列累加和
以前刚学的时候不会,补上去;用四个单调栈求出每个数在加或减的时候计算进的次数就好。
#include<iostream> #include<string> #include<cstring> #include<algorithm> #define ll long long using namespace std; ll num[400000]; ll a[400000],b[400000],c[400000],d[400000]; ll top=0; ll ak[400000],bk[400000],ck[400000],dk[400000]; int main() { //memset(ak,1,sizeof(ak)); //memset(bk,1,sizeof(bk)); //memset(ck,1,sizeof(ck)); //memset(dk,1,sizeof(dk)); //freopen("a.in","r",stdin); ll n; cin>>n; for(int i=1;i<=n;i++) { cin>>num[i]; } for(int i=1;i<=n;i++) { ak[i]=1; int w=top+1; while(num[i]>=num[a[top]]&&top!=0) { ak[i]+=ak[a[top]]; top--; } a[++top]=i; } top=0; for(int i=n;i>0;i--) { bk[i]=1; int w=top+1; while(num[i]>num[b[top]]&&top!=0) { bk[i]+=bk[b[top]]; top--; } b[++top]=i; } top=0; for(int u=1;u<=n;u++) { ck[u]=1; int w=top+1; while(num[u]<=num[c[top]]&&top!=0) { ck[u]+=ck[c[top]]; top--; } c[++top]=u; } int top=0; for(int u=n;u>=1;u--) { dk[u]=1; int w=top+1; while(num[u]<num[d[top]]&&top!=0) { dk[u]+=dk[d[top]]; top--; } d[++top]=u; } ll ans=0; for(int i=1;i<=n;i++) { ll w=ak[i]*bk[i]*num[i]; ll q=ck[i]*dk[i]*num[i]; ans+=w-q; } cout<<ans<<endl; return 0; }