题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3745

如果分治,就能在本层仅算过 mid 的区间了。

可以从中间到左边地遍历左边,给右边两个指针,表示第一个更新左边造成的最小值/最大值的位置。

两个位置共同的左边可以公式算长度,用左边的最值算;两个位置共同的右边可以预处理,处理出 算上长度(相对mid的)的最值乘积求和 与 不算长度的最值乘积求和(都是前缀),把前者加到答案里,后者乘上左边到mid的长度加到答案里即可;两个位置夹着的位置判断一下可以用左边的最大值还是最小值,所以要预处理右边最大值/最小值的算长度/不算长度前缀和,然后和公共右边一样的处理方法即可。

取模的地方要注意!可能加了一个东西,就不能再+mod、upd( ),而要直接upd( )。

注意把 l-1 位置的各种值赋成0。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5e5+5,mod=1e9;
int n,a[N],ans,s0[N],s1[N],s2[N];//s:可加入ans,相对长度
int ml0[N],ml1[N],ml2[N];//ml:单纯乘积相加
int rdn()
{int ret=0;bool fx=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();return fx?ret:-ret;
}
void upd(int &x){x-=(x>=mod?mod:0);}
ll calc(int a){return (ll)a*(a+1)>>1ll;}
int dis(int x,int y){return y-x+1;}
void solve(int l,int r)
{if(l==r){s2[l]=ml2[l]=(ll)a[l]*a[l]%mod;s1[l]=ml1[l]=s0[l]=ml0[l]=a[l];s2[l-1]=s1[l-1]=s0[l-1]=ml2[l-1]=ml1[l-1]=ml0[l-1]=0;//
        ans+=s2[l]; upd(ans);return;}int mid=l+r>>1;solve(l,mid); solve(mid+1,r);int lo=a[mid],hi=a[mid],p0=mid+1,p1=mid+1;for(int i=mid,cd=1;i>=l;i--,cd++){hi=max(hi,a[i]); lo=min(lo,a[i]);while(a[p0]<=hi&&p0<=r) p0++;while(a[p1]>=lo&&p1<=r) p1++;int tl=min(p0,p1)-1,tr=max(p0,p1);
//        printf("l=%d r=%d hi=%d lo=%d p0=%d p1=%d\n",l,r,hi,lo,p0,p1);int d=dis(mid+1,tl);ans=(ans+( (ll)cd*d+calc(d) )%mod*lo%mod*hi)%mod;
//        printf("ans=%d ",ans);
ans=(ans+s2[r]-s2[tr-1])%mod+mod; upd(ans);ans=ans+(ll)(ml2[r]-ml2[tr-1])*cd%mod;//cd not dis(i,tr-1)if(ans<0) ans+=mod; else upd(ans);//if
//        printf("ans=%d ",ans);if(p1<p0)//最小值已更新
        {ans=ans+(ll)hi*(s1[tr-1]-s1[tl])%mod;if(ans<0)ans+=mod; else upd(ans);ans=(ans+(ll)(ml1[tr-1]-ml1[tl])*cd%mod*hi%mod);//cdif(ans<0) ans+=mod; else upd(ans);//if
        }if(p0<p1)//最大值已更新
        {
//            printf("tl=%d tr=%d dis(i,tl)=%d s0[%d]-s0[%d]=%d lo=%d mml=%d\n",
//            tl,tr,dis(i,tl),tr-1,tl,s0[tr-1]-s0[tl],lo,ml0[tr-1]-ml0[tl]);ans=ans+(ll)lo*(s0[tr-1]-s0[tl])%mod;if(ans<0)ans+=mod; else upd(ans);ans=(ans+(ll)(ml0[tr-1]-ml0[tl])*cd%mod*lo%mod);if(ans<0) ans+=mod; else upd(ans);//if
        }}hi=lo=a[l];s2[l]=ml2[l]=(ll)hi*lo%mod;  s1[l]=ml1[l]=lo; s0[l]=ml0[l]=hi;for(int i=l+1,d=2;i<=r;i++,d++){hi=max(hi,a[i]); lo=min(lo,a[i]);s2[i]=s2[i-1]+(ll)d*hi%mod*lo%mod; upd(s2[i]);s1[i]=s1[i-1]+(ll)d*lo%mod; upd(s1[i]);s0[i]=s0[i-1]+(ll)d*hi%mod; upd(s0[i]);ml2[i]=ml2[i-1]+(ll)hi*lo%mod; upd(ml2[i]);ml1[i]=ml1[i-1]+lo; upd(ml1[i]);ml0[i]=ml0[i-1]+hi; upd(ml0[i]);}s2[l-1]=s1[l-1]=s0[l-1]=ml2[l-1]=ml1[l-1]=ml0[l-1]=0;//
}
int main()
{n=rdn();for(int i=1;i<=n;i++)a[i]=rdn();solve(1,n);printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/Narh/p/9716621.html

bzoj 3745 [Coci2015]Norma——序列分治相关推荐

  1. 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 ...

  2. BZOJ3745: [Coci2015]Norma【CDQ】

    3745: [Coci2015]Norma 我们对于a序列分治,枚举左端点(从右往左)维护MINMINMIN和MAXMAXMAX,右端点同时更新两个指针j,k,表示a[mid+1,j]≤MAXa[mi ...

  3. SP22343 NORMA2 - Norma(分治优化复杂度)

    SP22343 NORMA2 - Norma 一看就像是一个序列分治的题目,求解序列上区间长度乘区间最大值最小值的和,然后考虑如何处理,分治之后每次就可以将右边部分分成三部分,然后对于这三部分可以批量 ...

  4. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  5. BZOJ.3648.寝室管理(点分治 树状数组)

    BZOJ \(Description\) 求在一棵树上加一条边后,有多少条至少有\(k\)个点的路径. \(n\leq10^5\). \(Solution\) 对于一棵树的情况,可以点分治. 用树状数 ...

  6. BZOJ 4921: 互质序列 数学 枚举

    4921: 互质序列 Time Limit: 1 Sec  Memory Limit: 256 MB Submit: 112  Solved: 61 [Submit][Status][Discuss] ...

  7. Bzoj 3730 震波 动态点分治

    Bzoj 3730 震波 题解: 和在线的边分治差不多. 就是将每层都信息都存下来. 然后对于每一层记录上一层的重心是哪个. 对于求和的话, 从自己的那层出发,然后暴力往上爬, 然后计算答案. 对于修 ...

  8. BZOJ 1176: [Balkan2007]Mokia( CDQ分治 + 树状数组 )

    考虑cdq分治, 对于[l, r)递归[l, m), [m, r); 然后计算[l, m)的操作对[m, r)中询问的影响就可以了. 具体就是差分答案+排序+离散化然后树状数组维护.操作数为M的话时间 ...

  9. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

最新文章

  1. java 倾斜校正_简述Java图像倾斜方法及实例
  2. 生活随笔[2005-06-08]
  3. 2011考研英语词汇最佳记忆法 考量你的遗忘曲线
  4. vue $set修改对象
  5. iptables详解--转
  6. Thread Group(线程组)
  7. SAP UI5 应用开发教程之六十二 - 基于 OData V4 的 SAP UI5 表格控件使用方法介绍
  8. WPF DataGrid 通过自定义表头模拟首行固定
  9. Python外(1)--try-expect
  10. java为学生s1的age属性_求解java程序,题目如下
  11. 如何解决ORA-28002 the password will expire within 7 days问题(密码快过期)
  12. ES6语法---箭头函数/关于this指向
  13. 拼小圈营销群_深圳弘辽科技电商:拼多多“砍单免费拿”:一场关于人性的较量...
  14. 【渝粤教育】国家开放大学2018年秋季 0179-21T数据库基础与应用 参考试题
  15. 使用slickedit代替sourceinsight
  16. 【SQLite】C++链接SQLite读数据乱码问题(非中文)
  17. 如何写Dockerfile,Dockerfile 参考文档
  18. IDEA(Java Web 开发) 实时代码模板合集
  19. Kubernetes 中的对象是如何删除的:Finalizers 字段介绍
  20. Vue搜索框显示最近(历史)搜索记录

热门文章

  1. 如何获得select被选中option的value和text和......
  2. Ev Dekorasyonu
  3. Android 6.0 Permission权限与安全机制
  4. 取消xp开机默认登陆账户
  5. [20151126]IMPDP TRANSFORM参数.TXT
  6. 程序员面试题100题第03题——求子数组的最大和
  7. 在二叉树中有两个结点m和n,若m是n的祖先,则使用后序遍历可以找到从m到n的路径
  8. PAT 乙级 1011. A+B和C (15) Java版
  9. LeetCode 49. Group Anagrams
  10. 【算法】动态规划笔记