[Codeforces 266E]More Queries to Array...(线段树+二项式定理)

题面

维护一个长度为\(n\)的序列\(a\),\(m\)个操作

  1. 区间赋值为\(x\)
  2. 查询\(\sum_{i=l}^r a_i(i-l+1)^k \mod 10^9+7\)

\(n,m \leq 10^5,k \leq 5\)

分析

根据二项式定理

\[(i-l+1)^k=\sum_{j=0}^k (-1)^{k-j} C_{k}^j i^j(l-1)^{k-j}
\]

那么

\(\begin{aligned}ans(l,r) &=\sum_{i=l}^r a_i(i-l+1)^k \\ &= \sum_{i=l}^r a_i\sum_{j=0}^k (-1)^{k-j} C_{k}^j i^j(l-1)^{k-j} \\ &= \sum_{i=l}^r \sum_{j=0}^k (a_ii^j) (-1)^{k-j} C_{k}^j (l-1)^{k-j} \\ &=\sum_{j=0}^k query(l,r,j) (-1)^{k-j} C_{k}^j (l-1)^{k-j}\end{aligned}\)

其中\(query(l,r,p)=\sum_{l=1}^r a_i^{p}\)

开\(k\)棵线段树,每棵维护\(\sum_{l=1}^r a_i^{p}\).提前预处理\(sum[i][j]\)表示\(\sum_{p=1}^{j} p^i\),修改为\(x\)的时候直接区间赋值为\(x(sum[i][r]-sum[i][l-1])\)

时间复杂度\(O(nk \log n)\)

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define maxn 100000
  5. #define mod 1000000007
  6. #define maxk 5
  7. using namespace std;
  8. typedef long long ll;
  9. int n,m;
  10. inline ll fast_pow(ll x,ll k){
  11. ll ans=1;
  12. while(k){
  13. if(k&1) ans=ans*x%mod;
  14. x=x*x%mod;
  15. k>>=1;
  16. }
  17. return ans;
  18. }
  19. inline ll inv(ll x){
  20. return fast_pow(x,mod-2);
  21. }
  22. ll fact[maxn+5];
  23. ll invfact[maxn+5];
  24. void ini_fact(int n){
  25. fact[0]=1;
  26. for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
  27. invfact[n]=inv(fact[n]);
  28. for(int i=n-1;i>=0;i--) invfact[i]=invfact[i+1]*(i+1)%mod;
  29. }
  30. inline ll C(int n,int m){
  31. return fact[n]*invfact[n-m]%mod*invfact[m]%mod;
  32. }
  33. ll sump[maxk+5][maxn+5];
  34. void ini_pow(int n,int k){
  35. for(int i=0;i<=k;i++){
  36. for(int j=1;j<=n;j++){
  37. sump[i][j]=(sump[i][j-1]+fast_pow(j,i))%mod;
  38. }
  39. }
  40. }
  41. inline ll get_sump(int k,int l,int r){
  42. return (sump[k][r]-sump[k][l-1]+mod)%mod;
  43. }
  44. struct segment_tree{
  45. struct node{
  46. int l;
  47. int r;
  48. ll val;
  49. ll mark;
  50. }tree[maxn*4+5];
  51. int kk;//记录当前维护的是a[i]^k
  52. void push_up(int pos){
  53. tree[pos].val=(tree[pos<<1].val+tree[pos<<1|1].val)%mod;
  54. }
  55. void build(int l,int r,int *a,int pos){
  56. tree[pos].l=l;
  57. tree[pos].r=r;
  58. tree[pos].mark=-1;
  59. if(l==r){
  60. tree[pos].val=a[l]*fast_pow(l,kk);
  61. return;
  62. }
  63. int mid=(l+r)>>1;
  64. build(l,mid,a,pos<<1);
  65. build(mid+1,r,a,pos<<1|1);
  66. push_up(pos);
  67. }
  68. inline void add_mark(int pos,int mark){
  69. tree[pos].mark=mark;
  70. tree[pos].val=mark*get_sump(kk,tree[pos].l,tree[pos].r)%mod;
  71. }
  72. void push_down(int pos){
  73. if(tree[pos].mark!=-1){
  74. add_mark(pos<<1,tree[pos].mark);
  75. add_mark(pos<<1|1,tree[pos].mark);
  76. tree[pos].mark=-1;
  77. }
  78. }
  79. void update(int L,int R,int val,int pos){
  80. if(L<=tree[pos].l&&R>=tree[pos].r){
  81. add_mark(pos,val);
  82. return;
  83. }
  84. push_down(pos);
  85. int mid=(tree[pos].l+tree[pos].r)>>1;
  86. if(L<=mid) update(L,R,val,pos<<1);
  87. if(R>mid) update(L,R,val,pos<<1|1);
  88. push_up(pos);
  89. }
  90. ll query(int L,int R,int pos){
  91. if(L<=tree[pos].l&&R>=tree[pos].r){
  92. return tree[pos].val;
  93. }
  94. push_down(pos);
  95. int mid=(tree[pos].l+tree[pos].r)>>1;
  96. ll ans=0;
  97. if(L<=mid) ans=(ans+query(L,R,pos<<1))%mod;
  98. if(R>mid) ans=(ans+query(L,R,pos<<1|1))%mod;
  99. return ans;
  100. }
  101. }T[6];
  102. int a[maxn+5];
  103. int main(){
  104. char cmd[2];
  105. int l,r,x,k;
  106. scanf("%d %d",&n,&m);
  107. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  108. ini_fact(maxk);
  109. ini_pow(n,maxk);
  110. for(int i=0;i<=maxk;i++){
  111. T[i].kk=i;
  112. T[i].build(1,n,a,1);
  113. }
  114. for(int t=1;t<=m;t++){
  115. scanf("%s",cmd);
  116. if(cmd[0]=='='){
  117. scanf("%d %d %d",&l,&r,&x);
  118. for(int i=0;i<=maxk;i++) T[i].update(l,r,x,1);
  119. }else{
  120. scanf("%d %d %d",&l,&r,&k);
  121. ll ans=0;
  122. //按照二项式定理,把a[i](i-l+1)^k展开
  123. //(-1)^j*C(k,j)*a[i]*i^j*(l-1)^(k-j)
  124. for(int j=0;j<=k;j++){
  125. // printf("db: %lld\n",fast_pow(-1,j));
  126. // printf("db: %lld\n",C(k,j));
  127. // printf("db: %lld\n",T[j].query(l,r,1));
  128. // printf("db: %lld\n",fast_pow(l-1,k-j));
  129. ans+=fast_pow(-1,k-j)*C(k,j)%mod*T[j].query(l,r,1)%mod*fast_pow(l-1,k-j)%mod;
  130. ans=(ans+mod)%mod;
  131. ans%=mod;
  132. }
  133. printf("%lld\n",ans);
  134. }
  135. }
  136. }

[Codeforces 266E]More Queries to Array...(线段树+二项式定理)的更多相关文章

  1. 暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)

    比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求.结果易想而知,超时了. 比赛后搜了搜题解,恍然大悟. 思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子.   ...

  2. CodeForces 266E More Queries to Array...(线段树+式子展开)

    开始觉得是规律题的,自以为是的推了一个规律,结果测试数据都没过....看了love神的博客才发现只是把式子展开就找到规律了.不过挺6的是我虽然想错了,但是维护的的东西没有错,只是改改(改了进两个小时好 ...

  3. Codeforces 1114F Please, another Queries on Array? 线段树

    Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...

  4. codeforces 719E E. Sasha and Array(线段树)

    题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...

  5. [Codeforces266E]More Queries to Array...——线段树

    题目链接: Codeforces266E 题目大意:给出一个序列$a$,要求完成$Q$次操作,操作分为两种:1.$l,r,x$,将$[l,r]$的数都变为$x$.2.$l,r,k$,求$\sum\li ...

  6. Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]

    Codeforces 洛谷:咕咕咕 CF少有的大数据结构题. 思路 考虑一些欧拉函数的性质: \[ \varphi(p)=p-1\\ \varphi(p^k)=p^{k-1}\times (p-1)= ...

  7. Codeforces 719 E. Sasha and Array (线段树+矩阵运算)

    题目链接:http://codeforces.com/contest/719/problem/E 题意:操作1将[l, r] + x; 操作2求f[l] + ... + f[r]; 题解:注意矩阵可以 ...

  8. Can you answer these queries? HDU 4027 线段树

    Can you answer these queries? HDU 4027 线段树 题意 是说有从1到编号的船,每个船都有自己战斗值,然后我方有一个秘密武器,可以使得从一段编号内的船的战斗值变为原来 ...

  9. [Codeforces 280D]k-Maximum Subsequence Sum(线段树)

    [Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...

随机推荐

  1. ETL工具-KETTLE教程专栏1----术语和定义

    1-资源库 资源库是用来保存转换任务的,用户通过图形界面创建的的转换任务可以保存在资源库中.        资源库可以使多用户共享转换任务,转换任务在资源库中是以文件夹形式分组管理的,用户可以自定义文 ...

  2. Python基础之赋值运算符

    如下图所示,假设变量a = 10, b = 20

  3. 2016 Multi-University Training Contest 4 部分题解

    1001,官方题解是直接dp,首先dp[i]表示到i位置的种类数,它首先应该等于dp[i-1],(假设m是B串的长度)同时,如果(i-m+1)这个位置开始到i这个位置的这一串是和B串相同的,那么dp[ ...

  4. $\LaTeX$数学公式大全6

    $6\ Binary\ Operation/Relation\ Symbols$$\ast$ \ast$\star$ \star$\cdot$ \cdot$\circ$ \circ$\bullet$ ...

  5. [题解] [HNOI2014] 世界树

    题面 [HNOI2014]世界树 题解 从数据范围很容易看出是个虚树DP(可惜看出来了也还是不会做) 虚树大家应该都会, 不会的话自己去搜吧, 我懒得讲了, 我们在这里只需要考虑如何DP即可 首先我们 ...

  6. 0.JQuery安装

    jQuery 安装 网页中添加 jQuery 可以通过多种方法在网页中添加 jQuery. 您可以使用以下方法: 从 jquery.com 下载 jQuery 库 从 CDN 中载入 jQuery, ...

  7. HttpClient : java.net.SocketException: Connection reset

    1. 问题排查 httpclient : 4.5.5 排查过程 : 一次SocketException:Connection reset 异常排查 主要原因 : 调用 http 请求时发生了 Sock ...

  8. onReachBottom 注意事项

    onReachBottom使用注意 可在pages.json里定义具体页面底部的触发距离onReachBottomDistance,比如设为50,那么滚动页面到距离底部50px时,就会触发onReac ...

  9. 【全网最优方法】JAVA初学:错误: 找不到或无法加载主类HelloWorld

    JAVA初学:错误: 找不到或无法加载主类 HelloWorld 我这是看的黑马2019网课(B站)出现的问题. 放一下别人的图,我也是大概的问题:就是javac没问题,java却无论怎么弄都报错. ...

  10. vue路由嵌套,对应展示的视图