對於每次詢問,輸出一行,表明詢問的答案。spa
給定長度爲n的序列:a1,a2,…,an,記爲a[1:n]。
相似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar。
若1≤l≤s≤t≤r≤n,則稱a[s:t]是a[l:r]的子序列。
如今有q個詢問,每一個詢問給定兩個數l和r,1≤l≤r≤n,求a[l:r]的不一樣子序列的最小值之和。php
例如,給定序列5,2,4,1,3,詢問給定的兩個數爲1和3,
那麼a[1:3]有6個子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],
這6個子序列的最小值之和爲5+2+4+2+2+2=17。ios
輸入文件的第一行包含兩個整數n和q,分別表明序列長度和詢問數。
接下來一行,包含n個整數,以空格隔開,第i個整數爲ai,即序列第i個元素的值。接下來q行,每行包含兩個整數l和r,表明一次詢問。
ide
對於每次詢問,輸出一行,表明詢問的答案。spa
1 ≤N,Q ≤ 100000,|Ai| ≤ 10^93d
1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 #include<cstdio>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cmath>
8 using namespace std; 9 typedef long long s64; 10
11 const int ONE = 100005; 12 const int INF = 2147483640; 13
14 int n,m; 15 int block[ONE],Q; 16 int a[ONE],pL[ONE],pR[ONE]; 17 int stk[ONE],top; 18 int Log[ONE],Bin[ONE],MinD[ONE][19],NumD[ONE][19]; 19 s64 Fl[ONE],Fr[ONE]; 20 s64 ans,Ans[ONE]; 21
22 struct power 23 { 24 int id; 25 int l,r; 26 }oper[ONE]; 27
28 inline bool cmp(const power &a,const power &b) 29 { 30 if(block[a.l] != block[b.l]) return block[a.l] < block[b.l]; 31 return a.r < b.r; 32 } 33
34 inline int get() 35 { 36 int res=1,Q=1; char c; 37 while( (c=getchar())<48 || c>57) 38 if(c=='-')Q=-1; 39 if(Q) res=c-48; 40 while((c=getchar())>=48 && c<=57) 41 res=res*10+c-48; 42 return res*Q; 43 } 44
45 inline void Pre_Rmq() 46 { 47 Log[0]=-1; for(int i=1;i<=n;i++) Log[i] = Log[i>>1] + 1; 48 Bin[0]=1; for(int i=1;i<=17; i++) Bin[i] = Bin[i-1] << 1; 49
50 for(int j=1;j<=17;j++) 51 for(int i=1;i<=n;i++) 52 if(i+Bin[j]-1 <= n) 53 { 54 int Next = i + Bin[j-1]; 55 if(MinD[i][j-1] < MinD[Next][j-1]) 56 MinD[i][j] = MinD[i][j-1], NumD[i][j] = NumD[i][j-1]; 57 else
58 MinD[i][j] = MinD[Next][j-1], NumD[i][j] = NumD[Next][j-1]; 59 } 60 else break; 61 } 62
63 inline int Get(int x,int y) 64 { 65 int T = Log[y - x +1]; 66 if(MinD[x][T] < MinD[y-Bin[T]+1][T]) return NumD[x][T]; 67 return NumD[y-Bin[T]+1][T]; 68 } 69
70 inline void MakepL() 71 { 72 top = 0; 73 for(int i=n;i>=1;i--) 74 { 75 while(top && a[stk[top]] > a[i]) 76 pL[stk[top--]] = i; 77 stk[++top] = i; 78 } 79 while(top) pL[stk[top--]] = 0; 80 for(int i=1;i<=n;i++) pL[i]++; 81 } 82
83 inline void MakepR() 84 { 85 top = 0; 86 for(int i=1;i<=n;i++) 87 { 88 while(top && a[stk[top]] > a[i]) 89 pR[stk[top--]] = i; 90 stk[++top] = i; 91 } 92 while(top) pR[stk[top--]] = n+1; 93 for(int i=1;i<=n;i++) pR[i]--; 94 } 95
96 inline s64 DealL(int l,int r) 97 { 98 int pos = Get(l,r); 99 return (s64)a[pos] * (r-pos+1) + Fr[l] - Fr[pos]; 100 } 101
102 inline s64 DealR(int l,int r) 103 { 104 int pos = Get(l,r); 105 return (s64)a[pos] * (pos-l+1) + Fl[r] - Fl[pos]; 106 } 107
108 int main() 109 { 110 n = get(); m = get(); Q = sqrt(n); 111 for(int i=1;i<=n;i++) 112 { 113 a[i] = get(); block[i] = (i-1)/Q+1; 114 MinD[i][0] = a[i]; NumD[i][0] = i; 115 } 116
117 Pre_Rmq(); MakepL(); MakepR(); 118 for(int i=1;i<=n;i++) Fl[i] = Fl[pL[i]-1] + (s64)(i-pL[i]+1) * a[i]; 119 for(int i=n;i>=1;i--) Fr[i] = Fr[pR[i]+1] + (s64)(pR[i]-i+1) * a[i]; 120
121
122 for(int i=1;i<=m;i++) 123 { 124 oper[i].id = i; 125 oper[i].l = get(); oper[i].r = get(); 126 } 127 sort(oper+1, oper+m+1, cmp); 128
129 int l = 1, r = 0; 130 for(int i=1;i<=m;i++) 131 { 132 while(r < oper[i].r) ans += DealR(l,++r); 133 while(oper[i].l < l) ans += DealL(--l,r); 134 while(r > oper[i].r) ans -= DealR(l,r--); 135 while(oper[i].l > l) ans -= DealL(l++,r); 136
137 Ans[oper[i].id] = ans; 138 } 139
140 for(int i=1;i<=m;i++) 141 printf("%lld\n",Ans[i]); 142 }