首先,如果我知道[l,r],要转移到[l,r+1]的时候,就是加上以r+1为右端点,[l,r+1]为左端点的区间的最小值,其他情况和这个类似
考虑这玩意怎么求
右端点固定的话,我左端点越往左走,这个最小值一定是越来越小
找到[l,r+1]范围内的最小值mi,那么在mi前面的第一个比mi小的位置(记为L[mi]),一定在这个范围外
而且相同的左端点,以这个位置为右端点和以r+1为右端点,区间的最小值是相同的(都是这个数)
所以可以只记f[i]表示以i为右端点,左端点在[1,i]的最小值的和
再问[l,r+1]的话,那就是f[r+1]-f[L[mi]]再减掉左端点在[L[mi]+1,l-1]这个范围内的,而这些的最小值都是mi
这个L用单调栈来求,mi用rmq来求
其他的转移同理
1 #include<bits/stdc++.h> 2 #define CLR(a,x) memset(a,x,sizeof(a)) 3 using namespace std; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 typedef pair<int,int> pa; 7 const int maxn=1e4+10,maxm=1e5+10; 8 9 inline ll rd(){ 10 ll x=0;char c=getchar();int neg=1; 11 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 12 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 13 return x*neg; 14 } 15 16 int N,NN,M,a[maxn]; 17 int stk[maxn],sh; 18 int L[maxn],R[maxn]; 19 pa rmq[maxn][20]; 20 ll f[maxn],g[maxn]; 21 struct Node{ 22 int l,r,i; 23 }que[maxm]; 24 ll ans[maxm]; 25 26 inline bool cmp(Node a,Node b){ 27 return a.l/NN==b.l/NN?a.r<b.r:a.l<b.l; 28 } 29 30 inline pa getmin(int l,int r){ 31 int m=log2(r-l+1); 32 return min(rmq[l][m],rmq[r-(1<<m)+1][m]); 33 } 34 35 inline void add(ll &n,int i,int bnd,int v){ 36 if(bnd<=i){ 37 pa p=getmin(bnd,i); 38 n+=v*(f[i]-f[L[p.second]]-1ll*p.first*(bnd-L[p.second]-1)); 39 }else{ 40 pa p=getmin(i,bnd); 41 n+=v*(g[i]-g[R[p.second]]-1ll*p.first*(R[p.second]-bnd-1)); 42 } 43 } 44 45 int main(){ 46 //freopen("","r",stdin); 47 int i,j,k; 48 N=rd(),M=rd();NN=sqrt(N); 49 for(i=1;i<=N;i++) a[i]=rd(); 50 for(i=N;i;i--){ 51 rmq[i][0]=make_pair(a[i],i); 52 for(j=1;(i+(1<<j)-1)<=N;j++) 53 rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]); 54 } 55 for(i=1;i<=N;i++){ 56 while(sh&&a[stk[sh]]>a[i]){ 57 R[stk[sh--]]=i; 58 }stk[++sh]=i; 59 }sh=0; 60 for(i=N;i;i--){ 61 while(sh&&a[stk[sh]]>a[i]){ 62 L[stk[sh--]]=i; 63 }stk[++sh]=i; 64 } 65 for(i=1;i<=N;i++){ 66 f[i]=f[L[i]]+1ll*(i-L[i])*a[i]; 67 } 68 for(i=N;i;i--){ 69 if(!R[i]) R[i]=N+1; 70 g[i]=g[R[i]]+1ll*(R[i]-i)*a[i]; 71 } 72 73 for(i=1;i<=M;i++){ 74 que[i].l=rd(),que[i].r=rd(),que[i].i=i; 75 } 76 sort(que+1,que+M+1,cmp); 77 int l=1,r=0;ll n=0; 78 for(i=1;i<=M;i++){ 79 while(r<que[i].r) add(n,++r,l,1); 80 while(r>que[i].r) add(n,r--,l,-1); 81 while(l<que[i].l) add(n,l++,r,-1); 82 while(l>que[i].l) add(n,--l,r,1); 83 ans[que[i].i]=n; 84 } 85 for(i=1;i<=M;i++) 86 printf("%lld ",ans[i]); 87 return 0; 88 } 89 /* 90 9 2 91 1 7 5 2 6 4 3 5 8 92 1 6 93 3 8 94 */