bzoj3745: [Coci2015]Norma 分治,单调队列

链接

bzoj

思路

首先\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=i}^{j}max(a_k)\)可以用单调队列求解。参见?
求解此题目,我们分治。计算\([l,mid]\)\([mid+1,r]\)的贡献。
我们从后向前枚举\(mid\)\(l\),定义为\(x\)。(\(A\)\([x,mid]\)中的最小值,\(B\)\([x,mid]\)中的最大值)
得到\(p\)(\([mid+1,r]\)中大于等于\(A\)的位置)和\(q\)(\([mid+1,r]\)中小于等于\(B\)的位置)
然后根据p,q的位置四种情况讨论,处理前缀和O1得到贡献。
显然p,q类似于单调队列是\(O(n)\)求得
代码有种简单但是恶心的感觉
复杂度\(O(nlogn)\)

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+7,inf=0x3f3f3f3f,mod=1e9;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
int n,a[N],ans;
int ma[N],mi[N],sum_mi[N],sum_ma[N],sum_mimai[N],sum_mima[N],sum_mii[N],sum_mai[N];
int jan(int a,int b) {
    int ans=(a-b);
    if(ans<0) ans+=mod;
    return ans;
}
void add(int &x,int y) {
    x+=y;
    if(x>=mod) x-=mod;
}
void cdq(int l,int r) {
    if(l>r) return;
    if(l==r) {ans=(1LL*a[l]*a[l]%mod+ans)%mod;return;}
    int mid=(l+r)>>1;
    cdq(l,mid),cdq(mid+1,r);

    sum_mi[mid]=sum_ma[mid]=sum_mima[mid]=sum_mimai[mid]=sum_mii[mid]=sum_mai[mid]=0;
    mi[mid]=inf,ma[mid]=0;
    for(int i=mid+1;i<=r;++i) {
        mi[i]=min(mi[i-1],a[i]);
        ma[i]=max(ma[i-1],a[i]);
        sum_mi[i]=(sum_mi[i-1]+mi[i])%mod;
        sum_ma[i]=(sum_ma[i-1]+ma[i])%mod;
        sum_mii[i]=(sum_mii[i-1]+1LL*mi[i]*i%mod)%mod;
        sum_mai[i]=(sum_mai[i-1]+1LL*ma[i]*i%mod)%mod;
        sum_mima[i]=(sum_mima[i-1]+1LL*mi[i]*ma[i]%mod)%mod;
        sum_mimai[i]=(sum_mimai[i-1]+1LL*mi[i]*ma[i]%mod*i%mod)%mod;
    }
    long long L,R;
    int p=mid,q=mid,A=a[mid],B=a[mid];
    int tot=ans;
    for(int i=mid;i>=l;--i) {
        A=min(A,a[i]),B=max(B,a[i]);
        while(p<r&&A<=a[p+1]) p++;
        while(q<r&&B>=a[q+1]) q++;
        L=mid+1,R=min(p,q);
        if(L<=R) 
            add(ans,1LL*A*B%mod*((L+R+2-2LL*i)*(R-L+1)/2%mod)%mod);
        L=p+1,R=q;
        if(L<=R)
            add(ans,1LL*B*jan(sum_mii[R],sum_mii[L-1])%mod),
            add(ans,1LL*jan(1,i)*B%mod*jan(sum_mi[R],sum_mi[L-1])%mod);
        L=q+1,R=p;
        if(L<=R)
            add(ans,1LL*A*jan(sum_mai[R],sum_mai[L-1])%mod),
            add(ans,1LL*jan(1,i)*A%mod*jan(sum_ma[R],sum_ma[L-1])%mod);
        L=max(p+1,q+1),R=r;
        if(L<=R)
            add(ans,jan(sum_mimai[R],sum_mimai[L-1])),
            add(ans,1LL*jan(1,i)*jan(sum_mima[R],sum_mima[L-1])%mod);
    }
}
int main() {
    n=read();
    for(int i=1;i<=n;++i) a[i]=read();
    cdq(1,n);
    printf("%d",ans);
    return 0;
}
全部评论

相关推荐

2025-12-25 16:26
已编辑
河北科技学院 Java
勇敢的牛油不服输:2800-300那不等于2500一个月吗兄弟们
点赞 评论 收藏
分享
秋招结束已经一段时间了&nbsp;一直在忙着毕业的事情&nbsp;浅浅总结一下自己的秋招经历吧~本人BG双非硕&nbsp;后端选手&nbsp;有一段小厂+腾讯暑期实习腾讯暑期转正loser秋招结束已经结束了有一段时间了总结一下秋招历程最大的感受就是秋招比起暑期更加卡学历秋招总共投了60多家吧一直面&nbsp;一直挂也投了两家银行科技岗&nbsp;都走到终面体检了都拒了(总体感觉本地的银行还是挺容易过的)可能本人更想去私企&nbsp;并且银行也挺卷听说一直到11月就只有一家小厂的offer并签约当保底然后也突然被WXG捞了&nbsp;本来都不对腾讯抱有希望了可能经过一整个秋招的面试积累吧&nbsp;以及本人有ACM经历&nbsp;WXG整体面试以做题偏多(一二面做了5道题&nbsp;4道hard)&nbsp;比较合自己胃口&nbsp;差不多半个月就把五轮面试过了进入录用评估&nbsp;但也一直没有结果到后面也陆陆续续有几家中厂也终面过泡池子一直到12月初华子给开了base杭州&nbsp;14a因为华子公积金的原因&nbsp;和小厂薪资上差距不大&nbsp;所以也一直犹豫是否毁约签华子&nbsp;但是内心也还对WXG抱有一丝幻想(虽然一直没有保温也没有任何消息)然后一直到12月中下旬&nbsp;华子要求去现场签约了&nbsp;但是WXG还是没有消息&nbsp;然后就连续发邮件和打电话催了好多次&nbsp;还是回复耐心等待直到华子签约那天&nbsp;经过内心挣扎已经决定毁约签华子了&nbsp;可能还是想平台更大一点吧&nbsp;然后最戏剧性的一幕来了&nbsp;就在我发毁约邮件没有5秒&nbsp;WXG打电话开奖了&nbsp;并且开奖也十分有诚意&nbsp;最终还是没有签约成功华子&nbsp;研究生期间也打了很多次华子的比赛还是对华子有感情的555整个秋招都是伴随着焦虑的&nbsp;我认为自己也是秋招大部分人的画像&nbsp;屡屡碰壁后不断怀疑自己&nbsp;但是可能自己也比较幸运吧&nbsp;但是也感谢自己在一次次陷入迷茫都没有放弃自己&nbsp;还是一直努力背八股&nbsp;刷题也祝各位牛友们共勉&nbsp;就算暂时没有好的offer&nbsp;不放弃一定会有好的结果的!!
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务