博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Codeforces266E]More Queries to Array...——线段树
阅读量:6555 次
发布时间:2019-06-24

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

题目链接:

 题目大意:给出一个序列$a$,要求完成$Q$次操作,操作分为两种:1、$l,r,x$,将$[l,r]$的数都变为$x$。2、$l,r,k$,求$\sum\limits_{i=l}^{r}a_{i}(i-l+1)^k$,其中$k\le 5$。

因为$k$比较小,对于序列的每个位置,维护出$a_{i}*i^{k}$的值,并用线段树维护区间和。因为存在区间赋值操作,我们再维护$f[i][j]$表示$\sum\limits_{x=1}^{i}x^j$(即$j$次幂的前缀和),用两个前缀和相减即可得到区间对应需要乘的数。对于询问,我们先求出区间中维护的各次幂的和,例如当$k=2$时,$ans=\sum a_{i}*i^2-2*(l-1)\sum a_{i}*i+(l-1)^2\sum a_{i}$,暴力将各次幂的和乘上对应常数相加即为答案。其他的$k$的情况同理,根据二项式展开推一下即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long#define mod 1000000007using namespace std;ll s[100010][6];ll sum[400010][6];ll num[400010];ll ans[6];int n,m;int x,k;char ch[3];int l,r;ll calc(int l,int r,int k){ return ((s[r][k]-s[l-1][k])%mod+mod)%mod;}void pushup(int rt){ for(int i=0;i<=5;i++) { sum[rt][i]=sum[rt<<1][i]+sum[rt<<1|1][i]; }}void pushdown(int rt,int l,int r){ if(num[rt]!=-1) { int mid=(l+r)>>1; num[rt<<1]=num[rt]; num[rt<<1|1]=num[rt]; for(int i=0;i<=5;i++) { sum[rt<<1][i]=num[rt]*calc(l,mid,i)%mod; sum[rt<<1|1][i]=num[rt]*calc(mid+1,r,i)%mod; } num[rt]=-1; }}void build(int rt,int l,int r){ num[rt]=-1; if(l==r) { scanf("%d",&x); for(int i=0;i<=5;i++) { sum[rt][i]=1ll*x*calc(l,l,i)%mod; } return ; } int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); pushup(rt);}void change(int rt,int l,int r,int L,int R,int k){ if(L<=l&&r<=R) { num[rt]=1ll*k; for(int i=0;i<=5;i++) { sum[rt][i]=1ll*k*calc(l,r,i)%mod; } return ; } pushdown(rt,l,r); int mid=(l+r)>>1; if(L<=mid) { change(rt<<1,l,mid,L,R,k); } if(R>mid) { change(rt<<1|1,mid+1,r,L,R,k); } pushup(rt);}void query(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R) { for(int i=0;i<=5;i++) { ans[i]+=sum[rt][i]; ans[i]%=mod; } return ; } pushdown(rt,l,r); int mid=(l+r)>>1; if(L<=mid) { query(rt<<1,l,mid,L,R); } if(R>mid) { query(rt<<1|1,mid+1,r,L,R); }}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { s[i][0]=1ll; for(int j=1;j<=5;j++) { s[i][j]=s[i][j-1]*i%mod; } } for(int i=1;i<=n;i++) { for(int j=0;j<=5;j++) { s[i][j]+=s[i-1][j]; s[i][j]%=mod; } } build(1,1,n); while(m--) { scanf("%s%d%d%d",ch,&l,&r,&k); if(ch[0]=='=') { change(1,1,n,l,r,k); } else { memset(ans,0,sizeof(ans)); query(1,1,n,l,r); ll res=0; if(k==0) { res+=ans[0],res%=mod; } else if(k==1) { res+=ans[1],res%=mod; res-=1ll*(l-1)*ans[0]%mod,res%=mod; } else if(k==2) { res+=ans[2],res%=mod; res-=2ll*(l-1)*ans[1]%mod,res%=mod; res+=1ll*(l-1)*(l-1)%mod*ans[0]%mod,res%=mod; } else if(k==3) { res+=ans[3],res%=mod; res-=3ll*(l-1)*ans[2]%mod,res%=mod; res+=3ll*(l-1)*(l-1)%mod*ans[1]%mod,res%=mod; res-=1ll*(l-1)*(l-1)%mod*(l-1)%mod*ans[0]%mod,res%=mod; } else if(k==4) { res+=ans[4],res%=mod; res-=4ll*(l-1)*ans[3]%mod,res%=mod; res+=6ll*(l-1)*(l-1)%mod*ans[2]%mod,res%=mod; res-=4ll*(l-1)*(l-1)%mod*(l-1)%mod*ans[1]%mod,res%=mod; res+=1ll*(l-1)*(l-1)%mod*(l-1)%mod*(l-1)%mod*ans[0]%mod,res%=mod; } else { res+=ans[5],res%=mod; res-=5ll*(l-1)*ans[4]%mod,res%=mod; res+=10ll*(l-1)*(l-1)%mod*ans[3]%mod,res%=mod; res-=10ll*(l-1)*(l-1)%mod*(l-1)%mod*ans[2]%mod,res%=mod; res+=5ll*(l-1)*(l-1)%mod*(l-1)%mod*(l-1)%mod*ans[1]%mod,res%=mod; res-=1ll*(l-1)*(l-1)%mod*(l-1)%mod*(l-1)%mod*(l-1)%mod*ans[0]%mod,res%=mod; } res=(res%mod+mod)%mod; printf("%lld\n",res); } }}

转载于:https://www.cnblogs.com/Khada-Jhin/p/10446448.html

你可能感兴趣的文章
Android Button事件
查看>>
IO流(PrintWriter) 很重要的一个类 核心
查看>>
python实现WordCount基础和拓展功能
查看>>
《开拓者研发团队》——基于弹幕评论的大数据分析平台项目的原型设计与开发...
查看>>
实践.Net Core在Linux环境下的第一个Hello World
查看>>
flask+redis实现抢购(秒杀)功能
查看>>
J2EE 十三个技术规范
查看>>
结对-象棋-测试过程
查看>>
SQLALchemy之介绍,基本使用
查看>>
堆——优先队列
查看>>
GDI+ Custom Controls with Visual C# 2005
查看>>
跨浏览器本地存储框架(store.js/USTORE.js/Box.js)
查看>>
css3关键帧动画实现轮播效果
查看>>
小白的进阶之路2
查看>>
通过python的import hooks实现像引用代码一样使用配置文件
查看>>
【Ecstore2.0】计划任务/队列/导入导出 的执行问题
查看>>
微信公众平台接入广告投放系统
查看>>
OpenCV学习(28) 轮廓
查看>>
js4数据类型、类型转换
查看>>
Html中Table的简单使用
查看>>