博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj3745: [Coci2015]Norma 分治,单调队列
阅读量:4455 次
发布时间:2019-06-07

本文共 2534 字,大约阅读时间需要 8 分钟。

链接

思路

首先\(\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 
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
<=a[p+1]) p++; while(q
=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;}

转载于:https://www.cnblogs.com/dsrdsr/p/10993609.html

你可能感兴趣的文章
hdu.5212.Code(莫比乌斯反演 && 埃氏筛)
查看>>
python学习记录一
查看>>
使用LINQ的Skip和Take函数分批获取数据
查看>>
IP通信基础 4月1日
查看>>
KeyProvider
查看>>
空指针为什么能调用成员函数?
查看>>
用MySQL的存储过程来实现一些经典函数
查看>>
React (2) -- State and Lifecycle
查看>>
【转】在EmEditor上编译并运行JAVA
查看>>
关于SqlDateTime溢出的问题
查看>>
jquery下php与ajax的数据交换方式
查看>>
魅蓝Note有几种颜色 魅蓝Note哪个颜色好看
查看>>
使用PullToRefresh实现下拉刷新和上拉加载
查看>>
透明度百分比与十六进制转换
查看>>
HBase表预分区
查看>>
arcgis desktop 10.1 license manager无法启动问题解决
查看>>
django select_related() 联表查询
查看>>
mysql 常用,使用经验
查看>>
NSBundle,UIImage,UIButton的使用
查看>>
vue-cli3 中console.log报错
查看>>