Rikka with Prefix Sum(组合数学)
Rikka with Prefix Sum
题目描述
For example, given an array A of length n and m queries. Each query gives an interval [l,r] and you need to calculate . How to solve this problem in O(n+m)? We can calculate the prefix sum array B in which Bi is equal to . And for each query, the answer is Br-Bl-1.
Since Rikka is interested in this powerful trick, she sets a simple task about Prefix Sum for you:
Given two integers n,m, Rikka constructs an array A of length n which is initialized by Ai = 0. And then she makes m operations on it.
There are three types of operations:
1. 1 L R w, for each index i ∈ [L,R], change Ai to Ai + w.
2. 2, change A to its prefix sum array. i.e., let A' be a back-up of A, for each i ∈ [1,n], change Ai to .
3. 3 L R, query for the interval sum .
The first line contains a single number t(1≤ t ≤ 3), the number of the testcases.
For each testcase, the first line contains two integers n,m(1 ≤ n,m ≤ 10^5)
And then m lines follow, each line describes an operation(1 ≤ L ≤ R≤ n, 0 ≤ w ≤ 10^9).
The input guarantees that for each testcase, there are at most 500 operations of type 3.
output:
For each query, output a single line with a single integer, the answer modulo 998244353.
test:
Intput:
1
100000 7
1 1 3 1
2
3 2333 6666
2
3 2333 6666
2
3 2333 6666
output
13002
58489497
12043005
中文题意:给定一个序列A,长度最长为100000,初始值为0,现在有三种操作:
1.对区间[l,r]中所有的数都加上一个值。
2.对整个序列求一次前缀和。
3.询问[l,r]区间内所有a的和。
现在对1,0,0,0求3次前缀和得到下图
可以发现(1,1)对右下角的点的贡献是
接下来我们定义一个变量now记录数组了进行了几次求数组前缀和也就是题目的2号操作。
对于操作1,在[l,r]区间内每个数增加w。
相当于在上次进行2号操作前,在点 L 增加w,在点 R+1 减少w。
例如:在3到5号位置增加1
序号 1 2 3 4 5 6 7 8 9
now 0 0 1 1 1 0 0 0 0 求前缀和后
now-1 0 0 1 0 0 -1 0 0 0 求前缀和前
对于询问的话只要求下次求完前缀和 (位置 R 的值) - (位置 L-1 的值)
对于进行前缀和操作只要将now++即可
具体操作看代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = ,mod=;
struct Stack
{
ll lie,time,value;
} st[maxn];
ll fac[maxn+],ifac[maxn+],top; ll quick_pow(ll a,ll b)
{
ll ans=;
while(b)
{
if(b&)
ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=;
}
return ans;
} void init()
{
fac[]=;
for(int i=; i<=maxn; i++)
fac[i]=1ll*fac[i-]*i%mod;
ifac[maxn]=quick_pow(fac[maxn],mod-);
for(int i=maxn-; i>=; i--)
ifac[i]=1ll*ifac[i+]*(i+)%mod;
} ll C(ll n,ll m)
{
return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
} inline ll solve(ll x,ll now)
{
if(x==)return ; ll sum = ;
for(int i=; i<top; i++) ///计算每个更新对点的贡献值
{ if(st[i].lie>x)continue;
ll lie = st[i].lie;
ll per = st[i].time;
ll value = st[i].value; ll aa = x-lie + now-per -;
ll bb = now-per -; sum = (sum + value*C(aa,bb)%mod)%mod;
}
return sum;
} int main()
{
init(); ///预处理阶乘和逆元将计算组合数的时间复杂度降为O(1)
ll t,n,m,op;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&n,&m);
ll now = ,l,r,value;
top = ;
while(m--)
{
scanf("%lld",&op);
if(op==)
{
scanf("%lld%lld%lld",&l,&r,&value);
st[top].value = value%mod,st[top].time=now-,st[top].lie=l;
top++;
st[top].value =(mod-value)%mod,st[top].time=now-,st[top].lie=r+;
top++;
///将更新存入数组
}
else if(op==)
{
now++;
}
else
{
scanf("%lld%lld",&l,&r);
ll ans = solve(r,now+)-solve(l-,now+);
ans = (ans+mod)%mod;
printf("%lld\n",ans);
}
}
}
return ;
}
最新文章
- setprecision、fixed、showpoint的用法总结
- Redhat 一则关于路由及DNS配置的实例
- 算法-MergeSort
- Memcached, Redis, MongoDB区别
- BZOJ1315 : Ural1557Network Attack
- jquery delay()介绍及使用指南
- Did not find handler method for springMVC资源文件扫描不到---关于spring的那些坑
- Jenkins插件hyper slaves源码分析
- 关于oracle 11g 64位与 32位的 plsql、及其他32位应用程序共存的问题
- fx-experience-tools
- 高性能MySql进化论(九):查询优化器常用的优化方式
- OpenStack最新版本Folsom架构解析
- Spring+SpringMVC+MyBatis深入学习及搭建(十一)——SpringMVC架构
- java对象序列化、反序列化
- css3学习之旅-css的基本语法(1)
- 对于for循环中使用let或var时,i的作用域范围的记录
- .Net MVC TextBoxFor 扩展 placeholder 与 class 属性
- centos7分区建议
- springmvc整合mybatis 配置文件
- tail -f 与 tail -F的区别
热门文章
- 【iOS】图片缩放动画
- Bean Validation完结篇:你必须关注的边边角角(约束级联、自定义约束、自定义校验器、国际化失败消息...)
- CSS3 filter 模糊滤镜的应用
- WinForm开发中通用附件管理控件设计开发参考
- Activiti6系列(4)- 三个war包的数据源及密码修改
- Netty学习(四)-TCP粘包和拆包
- 认识Linux工具
- [Spring cloud 一步步实现广告系统] 22. 广告系统回顾总结
- K8S学习笔记之filebeat采集K8S微服务java堆栈多行日志
- pak文件的打包和解包