Description

There is a river, which contains n stones from left to right. These stones are magic, each
one has a magic number Ai which means if you stand on the ith stone, you can jump to (i +1)th stone, (i+2)th stone, ..., (i+Ai)th stone(when i+Ai > n, you can only reach as far as n), you want to calculate the number of ways to reach the nth stone.
Notice: you can not jump from right to left! 
 

Input

Input starts with an integer T(1 <= T <= 10), denoting the number of test cases. Each test case contains an integer n(1 <= n <= 105), denoting the number stones. Next line contains n integers Ai(1 <= Ai <= 108). 

Output

For each test case, print the number of way to reach the nth stone module 109+7. 

Sample Input

3
5
1 2 3 4 5
1
10
2
2 1

Sample Output

3
1
1 题意:给你n个数,对于ai表示可以跳到i+1,i+2,i+3 …i + ai的位置,问到达最后一个位置有几种方法。
思路:第一次接触线段树。由于转移的关系,刚开始想使用DP,但是需要转移的数是一个区间,后来想到因为修改的是一个区间的值,想到用树状数组,但是区间修改的操作好像很烦阿
   最终被告知是线段树。
 #include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#define nods(x) tree[x]
#define lefs(x) tree[x << 1]
#define rigs(x) tree[x << 1 | 1]
using namespace std; const int INF = 0x3f3f3f3f;
const int MAX = ;
const int MOD = 1e9 + ; struct segtree
{
int l, r, ans; //区间范围
int add; //懒惰标记
}tree[MAX << ]; //单点修改
void change(int &bep, int val)
{
bep += val;
bep = (bep % MOD + MOD) % MOD;
}
//父节点更新
void pushup(int pos)
{
change(nods(pos).ans, lefs(pos).ans + rigs(pos).ans);
}
//构造线段树
void build(int p, int l, int r)
{
nods(p).l = l;
nods(p).r = r;
nods(p).ans = nods(p).add = ;
if(l == r && l == )
nods(p).ans = ;
if(l == r)
return ; int mid = (l + r) >> ;
build( p << , l, mid );
build( p << | , mid + , r);
pushup(p);
}
//向下更新叶 通过延迟标记更新
void pushdown(int p)
{
if(nods(p).add)
{
change(lefs(p).add, nods(p).add);
change(rigs(p).add, nods(p).add);
change(lefs(p).ans, nods(p).add);
change(rigs(p).ans, nods(p).add);
nods(p).add = ;
}
}
//询问
int query(int p, int bor)
{
if(nods(p).l == nods(p).r)//递归到最小叶,直接返回
return nods(p).ans;
pushdown(p); //先应用标记 再查询 int mid = (nods(p).l + nods(p).r) >> ;
if(bor <= mid)
return query(p << , bor); //查询下一层左儿子
else return query(p << | , bor); //查询下一层右儿子
}
//区间修改
void update(int p, int l, int r, int val)
{
if(nods(p).l >= l && nods(p).r <= r) //完全包含
{
change(nods(p).add, val); //延迟标记
change(nods(p).ans, val); //更新该点
return ;
}
pushdown(p); //向下更新
int mid = (nods(p).l + nods(p).r) >> ;
if(r <= mid) //[l,r] 被包含于 [pl,mid]
update(p << , l, r , val);
else if(l > mid) //[l,r] 被包含于 [mid,pr]
update(p << | , l, r, val);
else //中间截断
{
update(p << , l, mid, val);
update(p << | , + mid, r, val);
}
pushup(p);
} int main()
{
int T, t;
int ans, ss, ee, n;
cin >> T;
while(T--)
{
scanf("%d", &n);
build(, , n);
for(int i = ; i <= n; i++)
{
scanf("%d", &t);
ss = i + ;
ee = min(i+t, n);
ans = query(, i);
if(i!=n)
update(, ss, ee, ans);
}
printf("%d\n", query(, n));
}
}


NOJ/HUST 1095 校赛 Just Go 线段树模板题的更多相关文章

  1. [AHOI 2009] 维护序列(线段树模板题)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...

  2. hdu1823(二维线段树模板题)

    hdu1823 题意 单点更新,求二维区间最值. 分析 二维线段树模板题. 二维线段树实际上就是树套树,即每个结点都要再建一颗线段树,维护对应的信息. 一般一维线段树是切割某一可变区间直到满足所要查询 ...

  3. [POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]

    可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include &l ...

  4. HDU 1698 Just a Hook (线段树模板题-区间求和)

    Just a Hook In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of t ...

  5. UESTC - 1057 秋实大哥与花 线段树模板题

    http://acm.uestc.edu.cn/#/problem/show/1057 题意:给你n个数,q次操作,每次在l,r上加上x并输出此区间的sum 题解:线段树模板, #define _CR ...

  6. 2016多校8th 1008【线段树-神题】

    题意: T N M N个数 M个操作 一个数组A, 有3个操作 1 l r x,a[l]-a[r]都+x 2 l r,a[i]=sqrt(a[i]),l<=i<=r 3 l r,求和,a[ ...

  7. POJ - 3264 线段树模板题 询问区间最大最小值

    这是线段树的一个模板题,给出一串数字,然后询问区间的最大最小值. 这个其实很好办,只需把线段树的节点给出两个权值,一个是区间的最小值,一个是区间的最大值,初始化为负无穷和正无穷,然后通过不断地输入节点 ...

  8. 敌兵布阵 HDU - 1166 (树状数组模板题,线段树模板题)

    思路:就是树状数组的模板题,利用的就是单点更新和区间求和是树状数组的强项时间复杂度为m*log(n) 没想到自己以前把这道题当线段树的单点更新刷了. 树状数组: #include<iostrea ...

  9. zkw线段树模板题

    学了zkw线段树,觉得没什么必要刷专题的吧(切不动啊).. 那先放一个模板题吧(我绝不会和你说搬了一道树状数组模板题的!!!) 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加 ...

随机推荐

  1. Thunder团队第三周 - Scrum会议3

    Scrum会议3 小组名称:Thunder 项目名称:i阅app Scrum Master:代秋彤 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...

  2. Java学习个人备忘录之数组工具类

    下面主要讲解一个针对数组操作的工具类. a.java -- 工具类文件 //按理来说要先编译本文件, 然后再编译主函数 class ArrayTool { /* 获取整型数组的最大值 */ publi ...

  3. Qt窗口及控件-QTreeview/QTableView排序问题

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt-QTreeview/QTableView排序问题     本文地址:http://tec ...

  4. 原生js实现自定义alert风格和实现

    2018年6月29 最新更新 添加函数节流,解决多次点击问题,添加单例模式,提高代码性能. <!DOCTYPE html> <html lang="en"> ...

  5. 通过设置窗体的AcceptButton属性,可以设置窗体的“接受”按钮,若此设计,则用户每次按下Enter键都相当于单击该按钮

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. c#对xml的操作

    操作xml可以通过XElement对象,比较方便的使用列举以下几点: 把字符串转变成XElement,保存成xml文件,加载xml文件: //把字符串解析成XElement对象 string str ...

  7. Struts2自定义结果视图(servlet验证码)

    1.编写一个类实现com.opensymphony.xwork2.Result,或者继承org.apache.struts2.dispatcher.StrutsResultSupport 2.自定义的 ...

  8. BZOJ 1042 硬币购物(背包DP+容斥原理)

    可以看出这是个多重背包,运用单调队列优化可以使每次询问达到O(s).这样总复杂度为O(s*tot). 会TLE. 因为改题的特殊性,每个硬币的币值是不变的,变的只是每次询问的硬币个数. 我们不妨不考虑 ...

  9. BZOJ4570:[SCOI2016]妖怪——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4570 邱老师是妖怪爱好者,他有n只妖怪,每只妖怪有攻击力atk和防御力dnf两种属性.邱老师立志成 ...

  10. BZOJ2286:[SDOI2011]消耗战——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...