topic
Given a sequence of length n: a1,a2,...,an, denoted as a[1:n]. Similarly, a[l:r] (1≤l≤r≤N) refers to the sequence: al,al+1,...,ar-
1,ar. If 1≤l≤s≤t≤r≤n, then a[s:t] is said to be a subsequence of a[l:r]. Now there are q queries, each query is given two numbers l and r, 1≤l≤r≤n
, find the sum of the minimum values of different subsequences of a[l:r]. For example, given the sequence 5, 2, 4, 1, 3, and asking the given two numbers to be 1 and 3, then a[1:3] has
6 subsequences a[1:1], a[2:2 ],a[3:3],a[1:2],a[2:3],a[1:3], the sum of the minimum values of these 6 subsequences is 5+2+4+2+2+ 2=17.
input format
The first line of the input file contains two integers n and q, representing the sequence length and the number of queries, respectively. The next line contains n integers, separated by spaces
, and the ith integer is ai, which is the value of the ith element of the sequence. The next q lines, each containing two integers l and r, represent a query.
output format
For each query, output a line representing the answer to the query.
input sample
5 5
5 2 4 1 3
1 5
1 3
2 4
3 5
2 5
Sample output
28
17
11
11
17
hint
1 ≤N,Q ≤ 100000,|Ai| ≤ 10^9
answer
Considering Mo team,
we only need to consider how to extend the interval \(O(1)\)
Extending the left and right endpoints is similar,
taking the right endpoint as an example
The newly generated subintervals must be those subintervals with the new right endpoint \(r\) as the right endpoint,
then consider the influence of all left endpoints
from the position of the minimum value of the interval to the left endpoint of the interval, and the left endpoint is within this interval. The contribution must be the minimum value of the interval
. As for the contribution of the left endpoint in the right half of the interval, let's consider:
from \(r\) to a position smaller than \(A[r]\) \(pos\) , the answer Always \(A[r]\)
then start from \(pos\) , go to the left to a position smaller than \(A[pos]\) , the answer is always \(A[pos]\)
and so on
If you connect each position to the first position smaller than it, this is a tree structure, we only use \(O(1)\) to find the distance between the two points of the tree chain to solve the answer of the right half interval
Building a tree can be implemented with a monotonic stack
We can then use the \(ST\) table to maintain the minimum value to achieve \(O(1)\) extended range
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxn];
inline void build(int u,int v){
ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;
}
LL Ls[maxn],Rs[maxn];
LL mn[maxn][18],n,Q,A[maxn],fa[maxn],fa1[maxn],bin[30],Log[maxn],B;
LL st[maxn],top,vis[maxn];
void dfs1(int u){
vis[u] = true;
if (fa[u]) Ls[u] = Ls[fa[u]] + (u - fa[u]) * A[u];
Redge(u) {
fa[to = ed[k].to] = u;
dfs1(to);
}
}
void dfs2(int u){
vis[u] = true;
if (fa1[u]) Rs[u] = Rs[fa1[u]] + (fa1[u] - u) * A[u];
Redge(u) {
fa1[to = ed[k].to] = u;
dfs2(to);
}
}
void init(){
REP(j,17) REP(i,n){
if (i + bin[j] - 1 > n) break;
mn[i][j] = A[mn[i][j - 1]] <= A[mn[i + bin[j - 1]][j - 1]] ? mn[i][j - 1] : mn[i + bin[j - 1]][j - 1];
}
REP(i,n){
while (top && A[st[top]] > A[i]) top--;
if (top) build(st[top],i);
st[++top] = i;
}
REP(i,n) if (!vis[i]) fa[i] = 0,dfs1(i);
top = 0; memset(vis,0,sizeof(vis)); memset(h,0,sizeof(h)); ne = 1;
for (int i = n; i; i--){
while (top && A[st[top]] > A[i]) top--;
if (top) build(st[top],i);
st[++top] = i;
}
for (int i = n; i; i--) if (!vis[i]) fa1[i] = 0,dfs2(i);
}
int getmn(int l,int r){
int t = Log[r - l + 1];
return A[mn[l][t]] <= A[mn[r - bin[t] + 1][t]] ? mn[l][t] : mn[r - bin[t] + 1][t];
}
struct Que{int l,r,id,b;}q[maxn];
LL ans[maxn];
inline bool operator <(const Que& a,const Que& b){
return a.b == b.b ? a.r < b.r : a.l < b.l;
}
void solve(){
sort(q + 1,q + 1 + Q);
LL tot = 0,L = q[1].l,R = q[1].r,pos;
for (int i = L; i <= R; i++){
pos = getmn(L,i);
if (A[pos] == A[i]) tot += (i - L + 1) * A[i];
else tot += (pos - L + 1) * A[pos] + Ls[i] - Ls[pos];
}
ans[q[1].id] = tot;
for (int i = 2; i <= Q; i++){
while (L != q[i].l || R != q[i].r){
if (L > q[i].l){
L--;
pos = getmn(L,R);
if (A[pos] == A[L]) tot += (R - L + 1) * A[L];
else tot += (R - pos + 1) * A[pos] + Rs[L] - Rs[pos];
}
if (L < q[i].l){
pos = getmn(L,R);
if (A[pos] == A[L]) tot -= (R - L + 1) * A[L];
else tot -= (R - pos + 1) * A[pos] + Rs[L] - Rs[pos];
L++;
}
if (R < q[i].r){
R++;
pos = getmn(L,R);
if (A[pos] == A[R]) tot += (R - L + 1) * A[R];
else tot += (pos - L + 1) * A[pos] + Ls[R] - Ls[pos];
}
if (R > q[i].r){
pos = getmn(L,R);
if (A[pos] == A[R]) tot -= (R - L + 1) * A[R];
else tot -= (pos - L + 1) * A[pos] + Ls[R] - Ls[pos];
R--;
}
}
ans[q[i].id] = tot;
}
REP(i,Q) printf("%lld\n",ans[i]);
}
int main(){
bin[0] = 1; for (int i = 1; i <= 25; i++) bin[i] = bin[i - 1] << 1;
Log[0] = -1; for (int i = 1; i < maxn; i++) Log[i] = Log[i >> 1] + 1;
n = read(); Q = read();
REP(i,n) A[i] = read(),mn[i][0] = i;
init();
B = (int)sqrt(n) + 1;
REP(i,Q){
q[i].l = read(); q[i].r = read(); q[i].id = i; q[i].b = q[i].l / B;
}
solve();
return 0;
}