Norma

传送门

题意简化:

定义一个区间的贡献为 \(max*min*len\),求给定序列中所有子区间的总贡献和

题解

考虑 \(O(n*log_2n)\) 的复杂度的做法

数据结构??? yzhx太菜了,不会怎么O(n)枚举所有区间

还是考虑分治吧

每次对于每个区间的贡献则等于:

左半边区间的贡献+右半边区间的贡献+跨越mid的区间贡献

所以现在分治的大体思路就出来了,先递归处理左右半边,在加上跨越左右区间的影响

我们再来观察这个式子: \(max*min*len\)

想想有什么可优化的部分呢?

显然,对于每个区间的max和min在适当扩张区间长度的情况下是不会改变的

所以我们暴力求的话则会重复求很多次

有了大致思路,那么,我们现在来考虑怎么处理跨mid的子区间贡献

设当前区间的左端点为 L ,右端点为 R , mid 为该区间的中间位置

对于跨越mid的子区间

枚举子区间左端点 i ,先假设它的右端点就是mid,那么我们再慢慢向右拓展右端点,并加入答案

设: 子区间i~j的最大值为max,最小值为min,

在拓展过程中 min 第一次改变的位置是 p , max 第一次改变的位置是 q , p<q (反过来也差不多)

所以所有以 i 为左端点,右端点j在 mid+1 ~ R 之间的子区间都可以被分为三种类型:

j < p 时 ( \(min*max\) 不变) :

\[ans+= min*max* \sum_{j=mid+1}^{p-1}(j-i+1)
\]

p<=j<q 时(只有 min 和区间长度发生改变):

\[ans+= max * \sum_{j=p}^{q-1} min[j] * (j-i+1)
\]

--> $$ ans+=max* \sum_{j=p}^{q-1} min[j] j+max * (1-i)\sum_{j=p}^{q-1} min[j]) $$

q<j<=r 时(全都改变):

\[ans+= \sum_{j=p}^{q-1} max[j]*min[j] * (j-i+1)
\]

--> $$ ans+= \sum_{j=p}^{q-1} max[j]min[j] j+(1-i)\sum_{j=p}^{q-1} max[j]min[j]) $$

然后我们再把 $$max[i],min[i],max[i]i,min[i]i,max[i]min[i],max[i]min[i]*i $$都用前缀和记录就好

代码

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define get getchar()
#define ll long long
in int read()
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
return t;
}
const int mod=1e9;
const int _=500002;
int n;
ll mul_mx[_],mul_mn[_],ans,sum_mx[_],sum_mn[_],mx[_],mn[_],a[_],mnmx[_],mul_mnmx[_];
in ll add(ll a,ll b) { //加法取模
return (((a%mod)+(b%mod))+mod)%mod;
}
in ll mul(ll a,ll b) { //乘法取模
return ((a%mod*b%mod)+mod)%mod;
}
in ll getsum(ll a,ll b) { //高斯求和
return ((a+b)*(b-a+1)/2)%mod;
}
in void work(int l,int r)
{
// cout<<l<<' '<<r<<" :: "<<endl;
if(l==r) { ans=add(ans,mul(a[l],a[l]));return;}
int mid=l+r>>1;
work(l,mid);
work(mid+1,r);
mx[mid]=mn[mid]=a[mid];
sum_mx[mid]=sum_mn[mid]=mul_mx[mid]=mul_mn[mid]=mul_mnmx[mid]=mnmx[mid]=0;
for(re int i=mid+1;i<=r;i++) {
mx[i]=max(mx[i-1],a[i]);
mn[i]=min(mn[i-1],a[i]);
sum_mx[i]=add(sum_mx[i-1],mx[i]);
sum_mn[i]=add(sum_mn[i-1],mn[i]);
mul_mx[i]=add(mul_mx[i-1],mul(mx[i],i));
mul_mn[i]=add(mul_mn[i-1],mul(mn[i],i));
mul_mnmx[i]=add(mul_mnmx[i-1],mul(mul(mx[i],mn[i]),i));
mnmx[i]=add(mnmx[i-1],mul(mx[i],mn[i]));
} //预处理
ll maxx=0,minn=0x3f3f3f3f3f3f3f3f;
for(re int p=mid+1,q=mid+1,i=mid;i>=l;i--)
{
minn=min(minn,a[i]),maxx=max(maxx,a[i]);
while(p<=r&&minn<a[p]) p++;
while(q<=r&&maxx>a[q]) q++; //找到p和q
if(p<q)
{
ans=add(ans,mul(mul(minn,maxx),getsum(mid-i+2,p-i)));
ans=add(ans,add(mul(maxx,add(mul_mn[q-1],-mul_mn[p-1])),-mul(mul(i-1,maxx),add(sum_mn[q-1],-sum_mn[p-1]))));
ans=add(ans,add(add(mul_mnmx[r],-mul_mnmx[q-1]),mul(add(1,-i),add(mnmx[r],-mnmx[q-1]))));
} //套上之前讲的三个式子
else
{
ans=add(ans,mul(mul(minn,maxx),getsum(mid-i+2,q-i)));
ans=add(ans,add(mul(minn,add(mul_mx[p-1],-mul_mx[q-1])),-mul(mul(i-1,minn),add(sum_mx[p-1],-sum_mx[q-1]))));
ans=add(ans,add(add(mul_mnmx[r],-mul_mnmx[p-1]),mul(add(1,-i),add(mnmx[r],-mnmx[p-1]))));
}
}
}
int main()
{
n=read();
for(re int i=1;i<=n;i++) a[i]=read();
work(1,n);
cout<<ans<<endl;
}

SP22343 Norma--序列分治的更多相关文章

  1. bzoj 3745 [Coci2015]Norma——序列分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3745 如果分治,就能在本层仅算过 mid 的区间了. 可以从中间到左边地遍历左边,给右边两个 ...

  2. [CF888E] Maximum Subsequence 序列分治

    早期作品,不喜轻喷. LG传送门 序列分治板子题. 切这道题用了好长时间,所以想发篇题解作为纪念 . 首先,我们认真观察题目数据(面向数据做题是个好习惯),发现题目的\(n\)竟然只有\(35\),我 ...

  3. 算法复习——序列分治(ssoj光荣的梦想)

    题目: 题目描述 Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯.在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界.保卫这里的平衡与和谐.在那个时 ...

  4. 洛谷SP22343 NORMA2 - Norma(分治,前缀和)

    洛谷题目传送门 这题推式子恶心..... 考虑分治,每次统计跨过\(mid\)的所有区间的答案和.\(i\)从\(mid-1\)到\(l\)枚举,统计以\(i\)为左端点的所有区间. 我们先维护好\( ...

  5. 【BZOJ3745】[Coci2015]Norma cdq分治

    [BZOJ3745][Coci2015]Norma Description Input 第1行,一个整数N: 第2~n+1行,每行一个整数表示序列a. Output 输出答案对10^9取模后的结果. ...

  6. NORMA2 - Norma [cdq分治]

    题面 洛谷 你有一个长度为n的序列,定义这个序列中每个区间的价值是 \(Cost(i,j)=Min(Ai...Aj)∗Max(Ai...Aj)∗(j−i+1)Cost(i,j)=Min(A_{i}.. ...

  7. BZOJ 3745: [Coci2015]Norma(分治)

    题意 给定一个正整数序列 \(a_1, a_2, \cdots, a_n\) ,求 \[ \sum_{i=1}^{n} \sum_{j=i}^{n} (j - i + 1) \min(a_i,a_{i ...

  8. UVA 11990 ``Dynamic'' Inversion (序列分治)

    26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大. 本来想学习一下cdq分治的,看到论文上的凸包.斜率就暂时放一边了,只知道 ...

  9. bzoj 3745: [Coci2015]Norma【分治】

    参考:https://blog.csdn.net/lych_cys/article/details/51203960 真的不擅长这种-- 分治,对于一个(l,r),先递归求出(l,mid),(mid+ ...

随机推荐

  1. Spring Boot 第一弹,问候一下世界!!!

    持续原创输出,点击上方蓝字关注我吧 目录 前言 什么是Spring Boot? 如何搭建一个Spring Boot项目? 第一个程序 Hello World 依赖解读 什么是配置文件? 什么是启动类? ...

  2. 使用IDEA远程调试SpringBoot程序

    远程调试就是服务端程序运行在一台远程服务器上,我们在本地服务端的代码中设置断点(本地的代码必须与远端一致),进行调试.每当有请求到达远程服务器时能够在本地知道远端程序的运行情况. 1.点击Run 选择 ...

  3. spring初始(介绍、核心架构)

    1.spring介绍 Spring是个java企业级应用的开源开发框架.主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring框架目标是简化Java企业级应用开发,并通 ...

  4. spring-cloud-starter-openfeign 源码详细讲解

    1.测试环境搭建: 1.1 架构图: product服务提供一个接口: order服务通过feign的方式来调用product的接口: order服务需要引入依赖: <dependency> ...

  5. Paxos 协议

    可用性与一致性 为了向用户提供更好的服务体验,现代软件架构越来越注重系统的可用性availability. 正是在这种趋势的驱动下,微服务与容器化技术才能在今天大行其道. 而高可用架构的前提是冗余: ...

  6. 在C++中使用libuv时对回调的处理 (2)

    前情简介 在完成了第一版的<在C++中使用libuv时对回调的处理>之后,在对项目进行开发的时候,还是感觉有一些难受. 因为在实际操作的时候,需要构建一个结构体,并且需要对这个结构体的内存 ...

  7. C++读写ini配置文件GetPrivateProfileString()&WritePrivateProfileString()

    转载: 1.https://blog.csdn.net/fengbingchun/article/details/6075716 2. 转自:http://hi.baidu.com/andywangc ...

  8. Windows 系统蓝屏错误小全

    0 0x00000000 作业完成. 1 0x00000001 不正确的函数. 2 0x00000002 系统找不到指定的档案. 3 0x00000003 系统找不到指定的路径. 4 0x000000 ...

  9. FRP服务

    FRP服务 - Web服务 本服务提供Web内网穿透服务,并且开放端口 443和 80端口. 写在前面:提供公益FRP服务器:frp.dev.boselor.com,服务器在洛杉矶但是请勿用于违法用途 ...

  10. shell-变量的数值运算与特殊应用expr

    1. expr(evaluate expressions)命令的用法: expr命令一般用于整数值,当也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令行计算器. 语法:expr ex ...