P3246 [HNOI2016] sequence (sum of minimum values of all intervals in query l-r)

Posted by gudfry on Tue, 28 Dec 2021 20:49:49 +0100

In multi calibration, the problem of the sum of the maximum and minimum of all intervals in the query interval l-r is achieved, and many details are not easy to deal with. Looking at the problem solution, it is found that it is a similar original problem, so I intend to supplement the original problem first.
Solution:
ST Table + monotone stack + Mo team
Seeing the sum of the minimum values of the calculation interval, it is not difficult to think that it may be related to the monotone stack. Think again, it should be necessary to calculate how much each number contributes to this interval. Then you can think about Mo team when you see the offline operation, but unfortunately, you don't have much thinking here. I went to turn over the topic and suddenly realized it.
We'll consider Mo's transfer if we can O ( 1 ) O(1) O(1) find the contribution of the left end point to the whole interval and the contribution of the right end point to the interval
First, we can assume that the interval sequence between l-r is:
5 3 8 7 1 2 6 5
We try to calculate the contribution of the left endpoint to the whole interval.
5 3 3 3 1 1 1 1
We find that the sum of the above sequences is the contribution.
We can find a rule that the more to the right, the smaller the number will be. Then we first find the position of the interval minimum, and then multiply it by the interval minimum (r-minimum position), which is the contribution of 1 to the sequence.
How to find the sequence of 5, 3?
set up r [ i ] r[i] r[i] is the first position smaller than this number on the right of the current number.
We make a suffix and for the monotone stack, s u f [ i ] = s u f [ r [ i ] ] + a [ i ] ∗ ( r [ i ] − i ) suf[i]=suf[ r[i] ]+a[i]*(r[i]-i) suf[i]=suf[r[i]]+a[i]∗(r[i]−i)
Let imin be the minimum subscript between l-r
Then the calculation method in the paragraph on the left is s u f [ l ] − s u f [ i m i n ] suf[l]-suf[imin] suf[l] − suf[imin], it seems incorrect, but it is true. Why? Because we i m i n imin imin is the position of the minimum value of this interval, then when this suffix passes i m i n imin After imin, the modified value will not be modified to i m i n imin The values to the right of imin.

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int maxn = 5e5+10;

int n,m;
int a[maxn];
int anshou[maxn],ansqian[maxn];
int pre[maxn],suf[maxn],pos[maxn];
void init(){
    stack<int> s;
    for(int i=n;i>=1;i--){
        while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
        anshou[i]=s.empty()?n+1:s.top();
        s.push(i);
    }
    while(s.size()) s.pop();
    for(int i=1;i<=n;i++){
        while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
        ansqian[i]=s.empty()?0:s.top();
        s.push(i);
    }
    for(int i=1;i<=n;i++){
        pre[i]=pre[ansqian[i]]+a[i]*(i-ansqian[i]);
    }
    for(int i=n;i>=1;i--){
        suf[i]=suf[anshou[i]]+a[i]*(anshou[i]-i);
    }
}

int stmin[maxn][21],mn[maxn];


int stcmp(int x,int y){
	return a[x]<a[y]?x:y;
}
void init_st(){
    mn[0]=-1;
    for (int i=1;i<=n;i++){
        mn[i]=((i & (i-1))==0) ? mn[i-1]+1 : mn[i-1];
        stmin[i][0]=i;
    }
    for(int j=1;j<=mn[n];j++)
        for(int i=1;i+(1<<j)-1<=n;i++){
            stmin[i][j]=stcmp(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
        }
}
inline int rmq_min(int L,int R){
    int k=mn[R-L+1];
    return stcmp(stmin[L][k],stmin[R-(1<<k)+1][k]);
}

struct Q{
    int l,r,k;
}q[maxn];

struct rule{
    bool operator ()(const Q & a, const Q & b)const{
    if(pos[a.l]!=pos[b.l]) return a.l<b.l;
    if(pos[a.l]&1) return a.r<b.r;
    return a.r>b.r;   //Because when l moves to another block, the movement of r will be very obvious.
    }
};
int ans[maxn];

inline int upl(int l,int r){
    int id=rmq_min(l,r);
    return (r-id+1)*a[id]+suf[l]-suf[id];
}
inline int upr(int l,int r){
    int id=rmq_min(l,r);
    return (id-l+1)*a[id]+pre[r]-pre[id];
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    //int n,m;
    cin>>n>>m;
    int sz=sqrt(n);
    for(int i=1;i<=n;i++) cin>>a[i],pos[i]=i/sz;
    init();
    init_st();
    for(int i=1;i<=m;i++){
        cin>>q[i].l>>q[i].r;
        q[i].k=i;
    }

    sort(q+1,q+1+m,rule());
    int l=1,r=0,res=0;
    for(int i=1;i<=m;i++){
        while(q[i].l<l) res+=upl(--l,r);
        while(q[i].r>r) res+=upr(l,++r);
        while(q[i].l>l) res-=upl(l,r),l++;
        while(q[i].r<r) res-=upr(l,r),r--;
        ans[q[i].k]=res;
    }
    for(int i=1;i<=m;i++){
        cout<<ans[i]<<endl;
    }

    return 0;
}

Topics: data structure