比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求。结果易想而知,超时了。

比赛后搜了搜题解,恍然大悟。

思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子。
   这里要注意:k的值非常小,所以应该是将式子按二项式定理展开
   (i-L+1)^k=(i+(1-L))^k
   展开之后可以发现:我们可以在节点存储ai*i,ai*i^2,ai*i^3,ai*i^4,ai*i^5 (L<=i<=R)的累加和。
   至于关于(1-L)^j(j=0~5)可以预先枚举所有的L,预先处理一下用数组存储。
   展开式要用到组合,所以组合也要预先处理一下。
  
   当更新时,我们发现l<=i<=r区间中所有的ai都变为x,
   累加和分别为x*(L+...+R),x*(L^2+...+R^2),x*(L^3+...+R^3),...,x*(L^5+...+R^5)
   因此我们也要预先处理1^j+2^j+...+n^j的和,存到一个数组中去

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue> using namespace std;
const long long mod=;
const int maxn=*;
const int maxnN=;
int n,m,k;
int L,R;
long long ans;
int C[][];
long long S[maxnN][]; //S[i][j]存储(1-i)^j的值
long long LMi[maxnN][]; //LMi[i][j]存储i^j的值,1<=i<=n,即ai*i^j中的i^j
long long sum[maxnN][]; //sum[i][j] 表示1^j+2^j……+i^j的值
struct Node {
int left,right;
long long pow0,pow1,pow2,pow3,pow4,pow5; //powj: ai*i^j的和,j=0~5
bool lazy;
int add;
} tree[maxn]; void init1() {
C[][]=;
for(int i=; i<=; i++) {
C[i][]=;
C[i][i]=;
for(int j=; j<i; j++) {
C[i][j]=C[i-][j-]+C[i-][j];
}
}
} void init2() {
memset(sum,,sizeof(sum));
for(int i=; i<=n; i++) {
S[i][]=;
LMi[i][]=;
sum[i][]=i;
for(int j=; j<=; j++) {
LMi[i][j]=(LMi[i][j-]*i)%mod;
S[i][j]=(S[i][j-]*(-i)%mod+mod)%mod;
sum[i][j]=(sum[i-][j]+LMi[i][j])%mod;
}
}
} void pushUp(int rt) {
tree[rt].pow0=(tree[rt<<].pow0+tree[rt<<|].pow0)%mod;
tree[rt].pow1=(tree[rt<<].pow1+tree[rt<<|].pow1)%mod;
tree[rt].pow2=(tree[rt<<].pow2+tree[rt<<|].pow2)%mod;
tree[rt].pow3=(tree[rt<<].pow3+tree[rt<<|].pow3)%mod;
tree[rt].pow4=(tree[rt<<].pow4+tree[rt<<|].pow4)%mod;
tree[rt].pow5=(tree[rt<<].pow5+tree[rt<<|].pow5)%mod;
} void build(int left,int right,int rt) {
tree[rt].left=left;
tree[rt].right=right;
tree[rt].lazy=false;
tree[rt].add=;
if(left==right) {
scanf("%I64d",&tree[rt].pow0);
tree[rt].pow1=(tree[rt].pow0*LMi[left][])%mod;
tree[rt].pow2=(tree[rt].pow0*LMi[left][])%mod;
tree[rt].pow3=(tree[rt].pow0*LMi[left][])%mod;
tree[rt].pow4=(tree[rt].pow0*LMi[left][])%mod;
tree[rt].pow5=(tree[rt].pow0*LMi[left][])%mod;
return;
}
int mid=(left+right)>>;
build(left,mid,rt<<);
build(mid+,right,rt<<|);
pushUp(rt);
} void pushDown(int rt);
void update(int l,int r,int value,int rt) {
if(l==tree[rt].left && tree[rt].right==r) {
tree[rt].lazy=true;
tree[rt].add=value;
tree[rt].pow0=value*(((sum[r][]-sum[l-][])%mod+mod)%mod);
tree[rt].pow1=value*(((sum[r][]-sum[l-][])%mod+mod)%mod);
tree[rt].pow2=value*(((sum[r][]-sum[l-][])%mod+mod)%mod);
tree[rt].pow3=value*(((sum[r][]-sum[l-][])%mod+mod)%mod);
tree[rt].pow4=value*(((sum[r][]-sum[l-][])%mod+mod)%mod);
tree[rt].pow5=value*(((sum[r][]-sum[l-][])%mod+mod)%mod);
return;
}
pushDown(rt); int mid=(tree[rt].left+tree[rt].right)>>;
if(r<=mid) {
update(l,r,value,rt<<);
} else if(l>mid) {
update(l,r,value,rt<<|);
} else {
update(l,mid,value,rt<<);
update(mid+,r,value,rt<<|);
}
pushUp(rt); } void pushDown(int rt) {
if(tree[rt].lazy && tree[rt].left!=tree[rt].right) {
tree[rt<<].lazy=tree[rt<<|].lazy=true;
long long tmp=tree[rt].add; tree[rt<<].add=tree[rt].add;
tree[rt<<|].add=tree[rt].add; int mid=(tree[rt].left+tree[rt].right)>>;
//这里可以直接调用update方法对儿子进行更新
update(tree[rt].left,mid,tmp,rt<<);
update(mid+,tree[rt].right,tmp,rt<<|); tree[rt].add=;
tree[rt].lazy=false;
}
} long long query(int l,int r,int rt,int i) {
if(l==tree[rt].left && tree[rt].right==r) {
if(i==)
return tree[rt].pow0;
else if(i==)
return tree[rt].pow1;
else if(i==)
return tree[rt].pow2;
else if(i==)
return tree[rt].pow3;
else if(i==)
return tree[rt].pow4;
else if(i==)
return tree[rt].pow5;
}
pushDown(rt); int mid=(tree[rt].left+tree[rt].right)>>;
if(r<=mid) {
return query(l,r,rt<<,i)%mod;
} else if(l>mid) {
return query(l,r,rt<<|,i)%mod;
} else {
return (query(l,mid,rt<<,i)+query(mid+,r,rt<<|,i))%mod;
}
} int main() {
int x;
char ch[]; scanf("%d%d",&n,&m);
init1();
init2(); build(,n,);
for(int i=; i<=m; i++) {
scanf("%s",ch);
if(ch[]=='=') {
scanf("%d%d%d",&L,&R,&x);
update(L,R,x,);
} else {
scanf("%d%d%d",&L,&R,&k);
ans=; //for(int i=0;i<=k;i++){
for(int i=k; i>=; i--) {
//ans=((ans+((query(L,R,1,i)*C[k][i]%mod)*S[L][k-i]%mod))%mod+mod)%mod;
ans=(ans+((query(L,R,,i)*C[k][i]%mod)*S[L][k-i]%mod))%mod; } printf("%I64d\n",ans);
}
}
return ;
}

暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)的更多相关文章

  1. 暑假集训单切赛第一场 CF 191A Dynasty Puzzles

    题意不说了,看原题吧,思路见代码: #include <iostream> #include <stdio.h> #include <string.h> #incl ...

  2. 暑假集训单切赛第一场 UVA 1737 Mnemonics and Palindromes 3

    题意:求由a,b,c三个字母组成的长度为n的字符串,其任意连续的至少长度大于等于2的子字符串都不是回文,问这个字符串有多少种?并字典序输出 如果所有种类的字符串总长度大于100000个字符,就输出TO ...

  3. 暑假集训单切赛第一场 POJ 2309 BST(找规律的题)

    题意:给出一棵二分搜索树,再给一个节点编号n,求以这个节点为根节点的子树叶子节点的最大值与最小值. 首先求n所在的层数,他的层数就是他的因子中2的个数(规律). n的左右各有num=2^i-1个数.最 ...

  4. 暑假集训单切赛第二场 UVA 11988 Broken Keyboard (a.k.a. Beiju Text)(字符串处理)

    一开始不懂啊,什么Home键,什么End键,还以为相当于括号,[]里的东西先打印出来呢.后来果断百度了一下. 悲催啊... 题意:给定一个字符串,内部含有'['和']'光标转移指令,'['代表光标移向 ...

  5. 暑假集训单切赛第二场 UVA 10982 Troublemakers

    题意:将点放在两个集合,同一个集合的边保留,不同集合的边删去,使得边至少减少一半.  输出任何一种方案即可.如果不能,输出Impossible 思路:设如果两个人为一对捣蛋鬼,则two[i][j]=t ...

  6. 组队赛Day1第一场 GYM 101350 F. Monkeying Around(线段树)

    [题目大意] 有n只猴子坐在树上,m个笑话. 给出每个讲这个笑话的猴子的编号,笑话的编号,和笑话的影响半径. 如果一个树上的猴子听了没听过的笑话,会掉到树下.如果听过并且在树下,就会爬到树上. 问最后 ...

  7. Contest1585 - 2018-2019赛季多校联合新生训练赛第一场(部分题解)

    Contest1585 - 2018-2019赛季多校联合新生训练赛第一场 C 10187 查找特定的合数 D 10188 传话游戏 H 10192 扫雷游戏 C 传送门 题干: 题目描述 自然数中除 ...

  8. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  9. HDU6578 2019HDU多校训练赛第一场 1001 (dp)

    HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...

随机推荐

  1. Android四大组件之一:BroadCastReceiver(广播接收者)

    广播接受者是(BroadCastReceiver)是Android中的地大组件之一,之前学习了一些关于BroadCastReceiver方面的知识,今天回过头来发现已经快忘记的差不多了,毕竟现在是刚开 ...

  2. const type& 与 type& 的区别

    const type& 与 type& 是C/C++编程中容易混淆的两个知识点,现在以 cont int& 与 int& 为例讲解: 1.int& 讲解 int ...

  3. 记一次linux samba服务问题调试

    linux下samba服务加入windows域控后,samba共享名与合法用户名不应一致,否则无法访问此共享.

  4. SQL Server Profiler监控执行语句

    SQL Server Profiler监控执行语句,这个功能主要用在实时的监控对数据库执行了什么操作,从而及时有效的跟踪系统的运行. 常规配置选项,名称.模板.保存到文件(可以复用). 事件选择,可以 ...

  5. CentOS 普通用户设置sudo权限

    1.先切换到root用户下,输入命令 su 2.添加sudo文件的写权限,命令是: chmod u+w /etc/sudoers 3.编辑sudoers文件 vi /etc/sudoers 找到 ro ...

  6. laravel框架少见方法详解

    1.whereDate() 方法 $q->where('created_at', '>=', date('Y-m-d').' 00:00:00')); 以前查数据时,直接用where条件来 ...

  7. Python开发【第一篇】Python基础之反射

    反射 反射的作用:反射得作用是提高代码可读行. __import__导入模块和import导入模块的区别: __import__导入模块是通过字符串进行导入. import是常用得导入模块方法. 扩展 ...

  8. 1097. Deduplication on a Linked List (25)

    Given a singly linked list L with integer keys, you are supposed to remove the nodes with duplicated ...

  9. Java方法重载

    Java允许一个类中定义多个方法,只要参数列表不同就行了.如果同一个类中包含了两个或者两个以上的方法的方法名相同,但形参列表不同,则被称为方法重载. /* 参数类型不同的重载 */ public cl ...

  10. using System.Threading.Tasks;

    using System.Threading.Tasks; .Net并行库介绍——Task1