hdu 6989 / 2021“MINIEYE杯”中国大学生算法设计超级联赛(4)1005 Didn't I Say to Make My Abilities Average in the Next Life?!

https://acm.hdu.edu.cn/showproblem.php?pid=6989

题意:

定义一个区间[L,R]的平均值为(最大值+最小值)/2

若干次询问[l,r],求[l,r]子区间平均值的期望

 

对[l,r]求所有子区间的最大值之和+最小值之和

然后除以2再除以子区间个数

求子区间最小(大)值之和,是HNOI2016的一道题

https://www.cnblogs.com/TheRoadToTheGold/p/15150757.html

搬过来用即可

 

#include<bits/stdc++.h>

using namespace std;

#define N 200003

typedef long long LL;

int a[N];

int s[N],top;
LL fl[N],fr[N],gl[N],gr[N]; 
LL FL[N],FR[N],GL[N],GR[N];

int lg2[N];
int st[N][18],stp[N][18];
int ST[N][18],STP[N][18];

const int mod=1e9+7;

int query(int l,int r)
{
    int len=lg2[r-l+1];
    if(st[l][len]<st[r-(1<<len)+1][len]) return stp[l][len];
    return stp[r-(1<<len)+1][len]; 
}

int QUERY(int l,int r)
{
    int len=lg2[r-l+1];
    if(ST[l][len]>ST[r-(1<<len)+1][len]) return STP[l][len];
    return STP[r-(1<<len)+1][len]; 
}

int poww(int a,int b)
{
    int c=1;
    for(;b;a=1ll*a*a%mod,b>>=1)
        if(b&1) c=1ll*c*a%mod;
    return c;
}

int main()
{
    int T;
    int n,m;
    int l,r,p,P;
    long long ans;
    int inv2=poww(2,mod-2);
    for(int i=2;i<N;++i) lg2[i]=lg2[i>>1]+1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);        
        for(int i=1;i<=n;++i) 
        {
            st[i][0]=ST[i][0]=a[i];
            stp[i][0]=STP[i][0]=i;
        }
        for(int i=1;1<<i<=n;++i)
            for(int j=1;j+(1<<i)-1<=n;++j)
            {
                st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
                if(st[j][i]==st[j][i-1]) stp[j][i]=stp[j][i-1];
                else stp[j][i]=stp[j+(1<<i-1)][i-1];
            }
        for(int i=1;1<<i<=n;++i)
            for(int j=1;j+(1<<i)-1<=n;++j)
            {
                st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
                ST[j][i]=max(ST[j][i-1],ST[j+(1<<i-1)][i-1]);
                if(st[j][i]==st[j][i-1]) stp[j][i]=stp[j][i-1];
                else stp[j][i]=stp[j+(1<<i-1)][i-1];
                if(ST[j][i]==ST[j][i-1]) STP[j][i]=STP[j][i-1];
                else STP[j][i]=STP[j+(1<<i-1)][i-1];
            }
        a[0]=-2e9;
        s[top=0]=0;
        for(int i=1;i<=n;++i)
        {
            while(a[i]<=a[s[top]]) top--;
            fl[i]=(fl[s[top]]+1ll*(i-s[top])*a[i])%mod;
            gl[i]=gl[i-1]+fl[i];
            gl[i]%=mod;
            s[++top]=i;
        }
        a[n+1]=-2e9;
        s[top=0]=n+1;
        for(int i=n;i;--i)
        {
            while(a[i]<=a[s[top]]) top--;
            fr[i]=(fr[s[top]]+1ll*(s[top]-i)*a[i])%mod;
            gr[i]=gr[i+1]+fr[i];
            gr[i]%=mod;
            s[++top]=i;
        }
        a[0]=2e9;
        s[top=0]=0;
        for(int i=1;i<=n;++i)
        {
            while(a[i]>=a[s[top]]) top--;
            FL[i]=(FL[s[top]]+1ll*(i-s[top])*a[i])%mod;
            GL[i]=GL[i-1]+FL[i];
            GL[i]%=mod;
            s[++top]=i;
        }
        a[n+1]=2e9;
        s[top=0]=n+1;
        for(int i=n;i;--i)
        {
            while(a[i]>=a[s[top]]) top--;
            FR[i]=(FR[s[top]]+1ll*(s[top]-i)*a[i])%mod;
            GR[i]=GR[i+1]+FR[i];
            GR[i]%=mod;
            s[++top]=i;
        }
        for(int i=1;i<=m;++i) 
        {
            scanf("%d%d",&l,&r);
            p=query(l,r);
            ans=1ll*(p-l+1)*(r-p+1)%mod*a[p]%mod;
            ans+=gr[l]-gr[p]-1ll*fr[p]*(p-l)%mod;
            ans+=gl[r]-gl[p]-1ll*fl[p]*(r-p)%mod;
            P=QUERY(l,r);
            ans+=1ll*(P-l+1)*(r-P+1)%mod*a[P]%mod;
            ans+=GR[l]-GR[P]-1ll*FR[P]*(P-l)%mod;
            ans+=GL[r]-GL[P]-1ll*FL[P]*(r-P)%mod;
            ans%=mod;
            if(ans<0) ans+=mod;
            ans=ans*inv2%mod;
            ans=ans*poww(1ll*(r-l+1)*(r-l+2)/2%mod,mod-2)%mod;
            printf("%lld\n",ans);
        }
    }
}

 

posted @ 2021-08-17 10:09  TRTTG  阅读(75)  评论(0编辑  收藏  举报