P10173题解

P10173 maxiMINImax

题目传送门

题解

感觉还是比较套路的,而且不需要笛卡尔树,连我都能做出来

这种区间 \(\min,\max\) 的题不难想到单调栈,我们可以 \(O(n)\) 处理出有几个区间的最小/大值为 \(a_i\),记为 \(ln_i,lx_i\)。然后推一下式子,写成标准形式,即 \(\sum\limits_{i<j<k}ln_j\times lx_i\times lx_k\times (a_j-a_i)(a_j-a_k)\)

最后那个东西显然可以拆开,变成 \(a_i^2-a_ia_j-a_ia_k+a_ja_k\)

可以用权值树状数组求出 \(\sum\limits_{i=1}^{x-1}lx_i,\sum\limits_{i=1}^{x-1}lx_ia_i,\sum\limits_{i=x+1}^nlx_i,\sum\limits_{i=x+1}^nlx_ia_i\),简记为 \(l1_x,l2_x,r1_x,r2_x\),则答案为 \(\sum\limits_{i=1}^nln_i\times(a_i^2\times l1_i\times r1_i-a_i\times l2_i\times r1_i-a_i\times l1_i\times r2_i+l2_i\times r2_i)\),即可 \(O(n)\) 统计。

代码:

/*
 * @Author: operator_ 
 * @Date: 2024-02-18 15:43:22 
 * @Last Modified by: operator_
 * @Last Modified time: 2024-02-18 17:16:35
 */
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd() {
    int s=0,m=0;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
    while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
    return m?-s:s;
}
const int M=9712176;
int n,a[1000005],ans,st1[1000005],top1,st2[100005],top2;
int lmin[1000005],rmin[1000005],lmax[1000005],rmax[1000005];
int lenmin[1000005],lenmax[1000005],l1[1000005],l2[1000005],r1[1000005],r2[1000005];
struct Binary_Indexed_Tree {
	int t[1000005];
	int lb(int x) {return x&-x;}
	int sum(int x) {int s=0;for(int i=x;i;i-=lb(i)) s=(s+t[i])%M;return s;}
	void add(int x,int k) {for(int i=x;i<=n;i+=lb(i)) t[i]=(t[i]+k)%M;}
}t1,t2;
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=n;i++) {
        while(top1&&a[st1[top1]]>a[i]) top1--;
        lmin[i]=st1[top1];st1[++top1]=i;
        while(top2&&a[st2[top2]]<a[i]) top2--;
        lmax[i]=st2[top2];st2[++top2]=i;
    }
    st1[top1=0]=st2[top2=0]=n+1;
    for(int i=n;i>=1;i--) {
        while(top1&&a[st1[top1]]>a[i]) top1--;
        rmin[i]=st1[top1];st1[++top1]=i;
        while(top2&&a[st2[top2]]<a[i]) top2--;
        rmax[i]=st2[top2];st2[++top2]=i;
    }
    for(int i=1;i<=n;i++)
        lenmin[i]=(i-lmin[i])*(rmin[i]-i)%M,lenmax[i]=(i-lmax[i])*(rmax[i]-i)%M;
    for(int i=1;i<=n;i++) {
        l1[i]=t1.sum(a[i]),l2[i]=t2.sum(a[i]);
        t1.add(a[i],lenmax[i]);t2.add(a[i],lenmax[i]*a[i]%M);
    }
    for(int i=1;i<=n;i++) t1.t[i]=t2.t[i]=0;
    for(int i=n;i>=1;i--) {
        r1[i]=t1.sum(a[i]),r2[i]=t2.sum(a[i]);
        t1.add(a[i],lenmax[i]);t2.add(a[i],lenmax[i]*a[i]%M);
    }
    for(int i=1;i<=n;i++) {
        ans=(ans+a[i]*a[i]%M*l1[i]%M*r1[i]%M*lenmin[i]%M)%M;
        ans=(ans-a[i]*l2[i]%M*r1[i]%M*lenmin[i]%M+M)%M;
        ans=(ans-a[i]*l1[i]%M*r2[i]%M*lenmin[i]%M+M)%M;
        ans=(ans+l2[i]*r2[i]%M*lenmin[i]%M)%M;
    }
    cout<<ans;
    return 0;
}
posted @ 2024-02-18 19:39  operator-  阅读(23)  评论(0编辑  收藏  举报