給定長度爲 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na1,a2,⋯,an,記爲 a[1:n] a[1 \colon n]a[1:n]。相似地,a[l:r] a[l \colon r]a[l:r](1≤l≤r≤N 1 \leq l \leq r \leq N1≤l≤r≤N)是指序列:al,al+1,⋯,ar−1,ar a_{l}, a_{l+1}, \cdots ,a_{r-1}, a_ral,al+1,⋯,ar−1,ar。若 1≤l≤s≤t≤r≤n1\leq l \leq s \leq t \leq r \leq n1≤l≤s≤t≤r≤n,則稱 a[s:t] a[s \colon t]a[s:t]是 a[l:r] a[l \colon r]a[l:r] 的子序列。html
如今有 q qq 個詢問,每一個詢問給定兩個數 l ll 和 r rr,1≤l≤r≤n 1 \leq l \leq r \leq n1≤l≤r≤n,求 a[l:r] a[l \colon r]a[l:r] 的不一樣子序列的最小值之和。例如,給定序列 5,2,4,1,3 5, 2, 4, 1, 35,2,4,1,3,詢問給定的兩個數爲 1 11 和 3 33,那麼 a[1:3] a[1 \colon 3]a[1:3] 有 6 66 個子序列 a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3]a[1 \colon 1], a[2 \colon 2], a[3 \colon 3], a[1 \colon 2],a[2 \colon 3], a[1 \colon 3]a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],這 666 個子序列的最小值之和爲 5+2+4+2+2+2=175+2+4+2+2+2=175+2+4+2+2+2=17。node
輸入文件的第一行包含兩個整數 n nn 和 q qq,分別表明序列長度和詢問數。
接下來一行,包含 n nn 個整數,以空格隔開,第 i ii 個整數爲 ai a_iai,即序列第 iii 個元素的值。
接下來 q qq 行,每行包含兩個整數 l ll 和 r rr,表明一次詢問。ios
對於每次詢問,輸出一行,表明詢問的答案。ide
5 5 5 2 4 1 3 1 5 1 3 2 4 3 5 2 5
28 17 11 11 17
對於 100%100\%100% 的數據,1≤n,q≤100000,∣ai∣≤109 1 \leq n,q \leq 100000 ,|a_i| \leq 10^91≤n,q≤100000,∣ai∣≤109ui
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 using namespace std; int n,q,a[maxn],L[maxn],R[maxn],to[maxn]; void make(int i){ L[i]=R[i]=i; int l=i,r=i; while(a[l-1]>=a[i]&&l>1)l--; while(a[r+1]>=a[i]&&r<n)r++; L[i]=l;R[i]=r; } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)make(i); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(a[i]==a[j]){to[i]=j;break;} int x,y; while(q--){ long long ans=0; scanf("%d%d",&x,&y); for(int i=x;i<=y;i++){ if(to[i]&&i>=L[to[i]])continue; int l=max(x,L[i]),r=min(y,R[i]); ans+=1LL*(i-l+1)*(r-i+1)*a[i]; } cout<<ans<<endl; } }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 200010 using namespace std; long long lg[maxn],mn[maxn][26],a[maxn],mnid[maxn][26]; long long belong[maxn],Ans[maxn],fl[maxn],fr[maxn],sta[maxn],top; struct node{ int l,r,id; bool operator < (const node &b)const{ if(belong[l]==belong[b.l])return r<b.r; return belong[l]<belong[b.l]; } }q[maxn]; long long qread(){ long long i=0,j=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();} while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();} return i*j; } void pre(long long n){//st表 lg[1]=0; for(int i=2;i<=n;i++){ lg[i]=lg[i-1]; if(i==(1<<lg[i]+1))lg[i]++; } for(int i=n;i>=1;i--){ mn[i][0]=a[i]; mnid[i][0]=i; for(int j=1;i+(1<<j)-1<=n;j++){ mn[i][j]=min(mn[i][j-1],mn[i+(1<<j-1)][j-1]); if(mn[i][j]==mn[i][j-1])mnid[i][j]=mnid[i][j-1]; if(mn[i][j]==mn[i+(1<<j-1)][j-1])mnid[i][j]=mnid[i+(1<<j-1)][j-1]; } } } long long query(long long l,long long r){ long long k=lg[r-l+1]; if(mn[l][k]<mn[r-(1<<k)+1][k])return mnid[l][k]; return mnid[r-(1<<k)+1][k]; } void dp(long long n,long long *f){//單調棧 sta[top=1]=0; for(int i=1;i<=n;i++){ while(a[sta[top]]>a[i])top--; f[i]=(i-sta[top])*a[i]+f[sta[top]]; sta[++top]=i; } } long long up_r(long long l,long long r){ long long p=query(l,r+1); return (p-l+1)*a[p]+fl[r+1]-fl[p]; } long long up_l(long long l,long long r){ long long p=query(l-1,r); return (r-p+1)*a[p]+fr[l-1]-fr[p]; } int main(){ freopen("Cola.txt","r",stdin); int n,Q; n=qread();Q=qread(); a[0]=-(1LL<<60); for(int i=1;i<=n;i++)a[i]=qread(); pre(n);dp(n,fl); reverse(a+1,a+n+1); dp(n,fr); reverse(a+1,a+n+1);reverse(fr+1,fr+n+1); int block=sqrt(n)+1; for(int i=1;i<=n;i++)belong[i]=(i/block)+1; for(int i=1;i<=Q;i++){ q[i].l=qread();q[i].r=qread(); q[i].id=i; } sort(q+1,q+Q+1); a[0]=0; int l=1,r=1;long long ans=a[1]; for(int i=1;i<=Q;i++){ while(r<q[i].r)ans+=up_r(l,r++); while(r>q[i].r)ans-=up_r(l,--r); while(l>q[i].l)ans+=up_l(l--,r); while(l<q[i].l)ans-=up_l(++l,r); Ans[q[i].id]=ans; } for(int i=1;i<=Q;i++)cout<<Ans[i]<<endl; return 0; }