zoukankan      html  css  js  c++  java
  • 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
    ",ans);
            }
        }
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    先森,我们是不同的字符串,请自重!
    Linux 内核 链表 的简单模拟(2)
    Linux 内核 链表 的简单模拟(1)
    Ubuntu 截屏
    ubuntu windows 双系统 磁盘乱搞 grub 导致 error:no such partition grub rescue>
    计算十进制数转化成二进制时1的个数
    Ubuntu gedit 折叠插件
    Unix 进程通信基本概念
    左式堆
    双调巡游
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15151094.html
Copyright © 2011-2022 走看看