• bzoj 3745 [Coci2015]Norma


    题目的大意是求一个数列中任意一个区间的长度乘上区间最大值和最小值求和。

    我们二分来做这个题,每次递归处理,然后我们只需统计所有跨过中点的区间的贡献即可。

    我们枚举[l,mid]区间里的每一个数a[i] (l<=i<=mid),因为无论最大值和最小值随着区间扩大有单调性,所以我们维护两个指针,分别记录右面区间最远的能够到达的距离,满足[mid+1,p1] [mid+1,p2] 的区间最大/(最小值) 小于/(大于) 等于 [i,mid]的最大(最小)值。

    然后我们分三块来统计,[i,min(p1,p2)]内所有的区间  , i到[max(p1,p2),r] 的所有区间  ,   i到[min(p1,p2),max(p1,p2)]所有区间,自己推一下式子就行啦。(中间少取了两次模,wa了好多次,感觉自己好蠢。。。。。。) ——by VANE

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod=1e9;
    const int N=5e5+5;
    void add(ll &x,ll y) {x=((x+y)%mod+mod)%mod;}
    ll getsum(int l,int r){return 1ll*(l+r)*(r-l+1)/2%mod;}
    ll f1[N],f2[N],f3[N],f4[N],a[N],n,ans,f5[N],f6[N];
    ll mn[N],mx[N];
    void solve(int l,int r)
    {
        if(l==r) {add(ans,a[l]*a[l]%mod);return;}
        int mid=l+r>>1;
        solve(l,mid);solve(mid+1,r);
        mn[mid]=mod;mx[mid]=-mod;
        f1[r+1]=0;f2[r+1]=0;
        f3[mid]=0;f4[mid]=0;
        f5[mid]=0;f6[mid]=0;
        int p1,p2;
        for(int i=mid+1;i<=r;++i)
        {
            mn[i]=min(mn[i-1],a[i]);mx[i]=max(mx[i-1],a[i]);
            f3[i]=f3[i-1]+i*mx[i];
            f4[i]=f4[i-1]+i*mn[i];
            f3[i]%=mod;f4[i]%=mod;
            f5[i]=f5[i-1]+mx[i];f5[i]%=mod;
            f6[i]=f6[i-1]+mn[i];f6[i]%=mod;
        }
        for(int i=r;i>=mid+1;--i)
        {
            f1[i]=f1[i+1]+mx[i]*mn[i]%mod*i%mod;
            f2[i]=f2[i+1]+mx[i]*mn[i]%mod;
            f1[i]%=mod;f2[i]%=mod;
        }
        p1=mid+1;p2=mid+1;
        ll mxl=-mod,mnl=mod;
        for(int i=mid;i>=l;--i)
        {
            mxl=max(mxl,a[i]);
            mnl=min(mnl,a[i]);
            while(p2<=r&&mn[p2]>=mnl) p2++;
            while(p1<=r&&mx[p1]<=mxl) p1++;
            p1--;p2--;
            add(ans,getsum(mid+1-i+1,min(p1,p2)-i+1)*mxl%mod*mnl%mod);
            add(ans,f1[max(p1,p2)+1]-f2[max(p1,p2)+1]*(i-1)%mod);
            if(p1<=p2)
                add(ans,mnl*(f3[p2]-f3[p1]-1ll*(i-1)*(f5[p2]-f5[p1])%mod));
            else
                add(ans,mxl*(f4[p1]-f4[p2]-1ll*(i-1)*(f6[p1]-f6[p2])%mod));
        }
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;++i) scanf("%lld",a+i);
        solve(1,n);
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    django-带参数路由
    django-获取购物车商品数量-redis
    django-配置静态页面-celery/redis/nginx
    django-自定义文件上传存储类
    django-安装nginx及fastdfs-nginx-module
    linux压缩和解压缩命令
    django-文件上传和下载--fastDFS安装和配置
    django-缓存django-redis
    django-改写manage类-objects
    django-登录后得个人信息
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8067431.html
Copyright © 2020-2023  润新知