寫這個題又複習了一遍莫隊...詢問排序第一關鍵字是左端點的塊,第二關鍵字是右端點...另外,那四個 \(while\) 移動端點的順序不能亂寫...否則會出現 \(L>R\) 的尷尬狀況..若是樣例沒測出來這題可就爆零了...c++
#include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh; } const int MAXN=1e5+10; struct query { int l,r,bel,id; bool operator < (const query &rhs) const { if(bel!=rhs.bel) return bel<rhs.bel; if(r!=rhs.r) return r<rhs.r; return l<rhs.l; } } q[MAXN]; int a[MAXN]; int st[MAXN][18],stp[MAXN][18]; int n,Q; int sl[MAXN],sr[MAXN]; int stk[MAXN],stkpos[MAXN],tp; ll suml[MAXN],sumr[MAXN]; ll res,ans[MAXN]; int mi,pos; inline void st_init() { for(int i=1;i<=n;++i) st[i][0]=a[i],stp[i][0]=i; for(int j=1;(1<<j)<=n;++j) for(int i=1;i+(1<<j)-1<=n;++i) { if(st[i][j-1]<st[i+(1<<(j-1))][j-1]) st[i][j]=st[i][j-1],stp[i][j]=stp[i][j-1]; else st[i][j]=st[i+(1<<(j-1))][j-1],stp[i][j]=stp[i+(1<<(j-1))][j-1]; } } void query(int l,int r) { int k=log(r-l+1)/log(2.0); if(st[l][k]<st[r-(1<<k)+1][k]) mi=st[l][k],pos=stp[l][k]; else mi=st[r-(1<<k)+1][k],pos=stp[r-(1<<k)+1][k]; } void addl(int L,int R) { query(L,R); ll delta=1LL*(R-pos+1)*mi; delta+=sumr[L]-sumr[pos]; res+=delta; } void reml(int L,int R) { query(L,R); ll delta=1LL*(R-pos+1)*mi; delta+=sumr[L]-sumr[pos]; res-=delta; } void addr(int L,int R) { query(L,R); ll delta=1LL*(pos-L+1)*mi; delta+=suml[R]-suml[pos]; res+=delta; } void remr(int L,int R) { query(L,R); ll delta=1LL*(pos-L+1)*mi; delta+=suml[R]-suml[pos]; res-=delta; } void init() { st_init(); stk[++tp]=0; stkpos[tp]=0; for(int i=1; i<=n; ++i) { while(tp) { if(a[i]<=stk[tp]) --tp; else break; } sl[i]=stkpos[tp]; stk[++tp]=a[i]; stkpos[tp]=i; suml[i]=suml[sl[i]]+1LL*(i-sl[i])*a[i]; } tp=0; stk[++tp]=0; stkpos[tp]=n+1; for(int i=n; i>=1; --i) { while(tp) { if(a[i]<=stk[tp]) --tp; else break; } sr[i]=stkpos[tp]; stk[++tp]=a[i]; stkpos[tp]=i; sumr[i]=sumr[sr[i]]+1LL*(sr[i]-i)*a[i]; } } int main() { n=read(),Q=read(); int Blocksize=sqrt(Q); for(int i=1; i<=n; ++i) a[i]=read(); for(int i=1; i<=Q; ++i) { q[i].l=read(); q[i].r=read(); q[i].bel=q[i].l/Blocksize; q[i].id=i; } sort(q+1,q+1+Q); init(); int L=1,R=0; for(int i=1; i<=Q; ++i) { int l=q[i].l,r=q[i].r; while(R<r) addr(L,++R); while(L<l) reml(L++,R); while(L>l) addl(--L,R); while(R>r) remr(L,R--); ans[q[i].id]=res; } for(int i=1; i<=Q; ++i) printf("%lld\n",ans[i]); return 0; }