Codeforces Round #239 (Div. 1)C, 407C
题目链接:http://codeforces.com/contest/407/problem/C
题目大意:给一个长度为n的数列,m次操作,每次操作由(li, ri, ki)描述,表示在数列li到ri这段数字上分别加上C(j-li+ki, ki),要求输出最后得到的序列。(% 1e9+7)
数据范围:1<=n, m<=10^5, a[i]<=10^9
思路:区间上加一个函数,在线求和,这种题目之前遇到过。记得是在区间上加kd(l<=k<=r),解法是线段树处理,由于等差+等差=等差,所以满足线段树lazy所要求的一致性和可计算性。在上题中我发现他所加的值是杨辉三角的某一列,通过观察发现是一个k阶等差数列。因此我便用了上述思想解决。然而绞尽脑汁思考一天并没有想到可行的标记方法,不能做到不同阶等差数列的统一。因此看了官方题解,竟然是离线做法,方法如下:
先考虑简单情况,k=0时,问题演变成一个传统的问题:区间加1,离线询问各值。在l处+1,r + 1处-1,求前缀和即可。我们称1,-1的操作为原态,如果对原态做一次前缀和,我们便轻松得到了在各区间加上一个数字之后的结果,继续拓展,对这个区间再取前缀和,便得到了各区间加上一个一阶等差数列之后的结果,以此类推,对原态数列做k次取前缀和的操作,便得到了各区间加上首项为1的k - 1阶等差数列的结果,这里的前提是在r + 1的位置原态时并不是-1,应当是一个-比较大的数字(仔细考虑)。
回归原题,如果原题中的所有操作k都相同,我们就可以对于每个操作在初始全部为0的数列中“搭好原态”,也就是在l处+1,在r + 1处减一个什么值,然后再对原态序列做k + 1次取前缀和操作,加上题目中给的序列,便得到了答案。然而题目中的k不尽相同,如令K=Max(ki),我们最多做K次迭代前缀,在中途“不失时机”地插入原态,让他们“搭顺风车”,达到目标,不失为一种不错的策略。
上述思路大体描述完,对于实现官方给了一个很值得借鉴的技巧。由于“搭顺风车”的想法可想不可写,于是我们把原全为0的序列拉开变成K层这种初始序列,每一层代表了某阶等差数列的原态,最终我们逐层递推更新既清晰有简单。代码中是k阶等差把原态插入k + 1层,最后从K倒推到0,经过迭代,a[0][i]数列加上题目给的数字便是答案。
最后一个问题就是上述原态中r + 1中究竟该减多少的问题,其实就是各阶等差数列的前r-l+r项和,在杨辉三角里很容易发现是通过有规律的组合数表示的,这样对于每次操作,把k + 1层的l处+1, 前0 - k + 1层的r + 1处减掉相应的组合数即可。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL; const int MaxN = 1e5, MaxK = , Pt = 1e9 + ;
int n, m;
LL orig[MaxN + ], a[MaxK + ][MaxN + ], c[MaxN + * MaxK][MaxK + ]; void Init()
{
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) scanf("%I64d", &orig[i]);
c[][] = ;
for (int i = ; i <= n + * MaxK; i++)
{
c[i][] = ;
for (int j = ; j <= MaxK; j++)
c[i][j] = (c[i - ][j] + c[i - ][j - ]) % Pt;
}
} void Solve()
{
int l, r;
int K = , k;
for (int i = ; i <= m; i++)
{
scanf("%d%d%d", &l, &r, &k);
K = max(K, k);
a[k + ][l] = (a[k + ][l] + ) % Pt;
for (int j = ; j <= k + ; j++)
a[j][r + ] = (a[j][r + ] - c[r - l + k - j + ][k - j + ] + Pt) % Pt;
}
for (int i = K; i >= ; i--)
{
LL s = ;
for (int j = ; j <= n; j++)
{
s = (s + a[i + ][j]) % Pt;
a[i][j] = (s + a[i][j]) % Pt;
}
}
for (int i = ; i <= n; i++) a[][i] = (a[][i] + orig[i]) % Pt;
for (int i = ; i <= n; i++) printf("%I64d ", a[][i]);
} int main()
{
Init();
Solve();
}
总结:
1.高阶等差数列可由多次前缀和迭代定义,这样就更贴近了阶的定义(迭代的过程)。用线性的递推代替了求通项等等麻烦的事情。
2.一维操作过于繁琐时可考虑把一维的拉开变成多维,逐层处理,最后叠加。可以让代码清晰简单。
Codeforces Round #239 (Div. 1)C, 407C的更多相关文章
- Codeforces Round #415 (Div. 2)(A,暴力,B,贪心,排序)
A. Straight «A» time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- Codeforces Round #427 (Div. 2)—A,B,C,D题
A. Key races 题目链接:http://codeforces.com/contest/835/problem/A 题目意思:两个比赛打字,每个人有两个参数v和t,v秒表示他打每个字需要多久时 ...
- Codeforces Round #239 (Div. 2)
做了三个题,先贴一下代码...终于涨分了 A. Line to Cashier 水题 #include <iostream> #include <cstdio> #includ ...
- Codeforces Round #239 (Div. 2) C. Triangle
time limit per test:1 secondmemory limit per test:256 megabytesinput:standard inputoutput:standard o ...
- Codeforces Round #239 (Div. 1) 二项式差分
C - Curious Array 思路:对于区间[l, r]每个数加上C(i - l + k, k), 可以在l处+1, 在r+1处-1, 然后做k+1次求前缀和操作,然后就可以写啦. 然后逐层求前 ...
- Codeforces Round #372 (Div. 2) A ,B ,C 水,水,公式
A. Crazy Computer time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- Codeforces Round #371 (Div. 2) A ,B , C 水,水,trie树
A. Meeting of Old Friends time limit per test 1 second memory limit per test 256 megabytes input sta ...
- Codeforces Round #239(Div. 2) 做后扯淡玩
今天补了下 cf 239div2 顿时信心再度受挫 老子几乎已经木有时间了啊 坐着等死的命.哎!!! 到现在还只能做大众题,打铁都不行. 每次D题都是有思路敲错,尼玛不带这么坑爹的. 哎!不写了,写这 ...
- Codeforces Round #239 (Div. 1)
B. Long Path time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
随机推荐
- 006-动态生成验证码Servlet代码模板
package checking; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java ...
- jsp模板添加URL定位语句
html的head头中加入以下语句,方便url链接诶编写定位 <base href="${pageContext.request.scheme}://${pageContext.req ...
- [PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法
问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...
- [转]ASP.NET Web API基于OData的增删改查,以及处理实体间关系
本文转自:http://www.cnblogs.com/darrenji/p/4926334.html 本篇体验实现ASP.NET Web API基于OData的增删改查,以及处理实体间的关系. 首先 ...
- MySQL函数库
MySQL函数库,这个函数库是一个外部函数库!这个函数提供了对于MySQL数据库进行操作的常用函数,如连接MySQL服务器.打开数据库.执行SQL语句等.所以这个函数库的功能对于我们来说是非常重要的! ...
- gc原理小结
一.相关概念 基本回收算法 1. 引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0 ...
- go get 下载需要的相关工具
文档来源: https://code.google.com/p/go-wiki/wiki/GoGetTools 被墙了,所以转在这个备用. Installing Version Control Too ...
- JS十进制转二进制(控制位数)
主要需求:十进制转二进制,可以控制指定的位数. 转化显示后的二进制数为bin-bit中输入的数字宽度.dec-number为5,bin-bit为5,则转化后数字为00101.如果bin-bit小于转化 ...
- Web前端面试指导(十三):css样式的优先级是怎么样的?
题目点评 CSS样式的优先级规则给人的感觉总是摸不透,更不用说怎么去表达了,在网络上流传着很多版本,描述的都很复杂也不全面,看了之后还是不满意.我来给大家介绍一个比较系统.全面有比较容易记住的规则吧! ...
- Regular Expression学习笔记
正则写法 var re = /a/;//简写 /.../里不能为空,因为会误以为是注释: var re = new RegExp('a'); 新建一个RegExp对象:和新建Array对象,Objec ...