Problem 1050: Just Go

Time Limits:  3000 MS   Memory Limits:  65536 KB

64-bit interger IO format:  %lld   Java class name:  Main

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), at first, you stand on 1th
stone, 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 <= 1e5), denoting the number stones. Next line contains n integers Ai(1 <= Ai <= 1e8).

Output

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

Sample Input

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

Output for Sample Input

3
1
1

校赛那会儿的题目,主要操作就是区间更新、单点查询,树状数组和线段树都可以,树状数组的简单很多也好写很多,线段树嘛,线段树的模版题自行体会。

主要解题思路:刚开始肯定是1号石头初始化为1,其他的都是0,这个相信很好理解,然后就是往后覆盖区间,但却不是简单的覆盖,为了弄懂到底如何操作举个例子先,比如我到3号有a种路线,到4号有几种(假设4号只与3号连通)?当然跟3号一样,就是a种,如果3号可以跳跃的步数不止1即可以跳到5号上呢?此时会变成P5=P4+P3,即3号过来有三种,4号过来有1种(只能跳一步过来)。加起来就是4种,3->5一种,3->4>-5三种,推广出去就是不停地往后覆盖自己这个点的可到达情况数就好了,最后的答案当然就是Pn

树状数组代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=100010;
const LL mod=1000000007;
LL tree[N],arr[N]; inline int lowbit(int k)
{
return k&(-k);
}
void add(int k,LL val)
{
while (k<=100000)
{
tree[k]+=val;
k+=lowbit(k);
}
}
LL getsum(int k)
{
LL r=0;
while (k)
{
r+=tree[k];
r%=mod;
k-=lowbit(k);
}
return r%mod;
}
void init()
{
MM(tree,0);
MM(arr,0);
}
int main(void)
{
int tcase,i,j,l,r,n;
scanf("%d",&tcase);
while (tcase--)
{
scanf("%d",&n);
init();
add(1,1);
add(2,-1);
for (i=1; i<=n; i++)
{
scanf("%I64d",&arr[i]);
}
for (i=1; i<=n; i++)
{
l=i+1;
r=i+arr[i];
if(r>n)
r=n;
LL pres=getsum(i);
add(l,pres);
add(r+1,-pres);
}
printf("%I64d\n",getsum(n));
}
return 0;
}

线段树代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=100010;
const LL mod=1e9+7;
struct info
{
LL l,mid,r;
LL sum,add;
};
info T[N<<2];
LL arr[N];
void pushup(int k)
{
T[k].sum=T[LC(k)].sum+T[RC(k)].sum;
}
void pushdown(int k)
{
T[RC(k)].add+=T[k].add;
T[RC(k)].sum+=T[k].add*(T[RC(k)].r-T[RC(k)].l+1);
T[LC(k)].add+=T[k].add;
T[LC(k)].sum+=T[k].add*(T[LC(k)].r-T[LC(k)].l+1);
T[k].add=0;
}
void build(int k,LL l,LL r)
{
T[k].l=l;
T[k].r=r;
T[k].mid=MID(T[k].l,T[k].r);
T[k].add=0;
T[k].sum=0;
if(l==r)
T[k].sum=(l==1&&r==1?1:0);
else
{
build(LC(k),l,T[k].mid);
build(RC(k),T[k].mid+1,r);
pushup(k);
}
}
void update(int k,LL l,LL r,LL val)
{
if(r<T[k].l||l>T[k].r)
return ;
if(l<=T[k].l&&r>=T[k].r)
{
T[k].add+=val;
T[k].sum+=val*(T[k].r-T[k].l+1);
T[k].sum%=mod;
}
else
{
if(T[k].add)
pushdown(k);
update(LC(k),l,r,val);
update(RC(k),l,r,val);
pushup(k);
}
}
LL query(int k,LL x)
{
if(T[k].l==T[k].r&&T[k].l==x)
return T[k].sum%mod;
if(T[k].add)
pushdown(k);
if(x<=T[k].mid)
return query(LC(k),x)%mod;
else if(x>T[k].mid)
return query(RC(k),x)%mod;
}
int main(void)
{
int tcase,i,j,n;
LL l,r,x,val;
scanf("%d",&tcase);
while (tcase--)
{
scanf("%d",&n);
MM(arr,0);
for (i=1; i<=n; i++)
scanf("%I64d",&arr[i]); build(1,1,n);
for (i=1; i<=n; i++)
update(1,(LL)(i+1),(LL)(i+arr[i]>n?n:i+arr[i]),query(1,i)); printf("%I64d\n",query(1,n)%mod);
}
return 0;
}

NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)的更多相关文章

  1. 【poj2155】Matrix(二维树状数组区间更新+单点查询)

    Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...

  2. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

  3. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  4. hdu1556 树状数组区间更新单点查询板子

    就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...

  5. HDU 1556 Color the ball (树状数组 区间更新+单点查询)

    题目链接 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽&quo ...

  6. 【树状数组区间修改单点查询+分组】HDU 4267 A Simple Problem with Integers

    http://acm.hdu.edu.cn/showproblem.php?pid=4267 [思路] 树状数组的区间修改:在区间[a, b]内更新+x就在a的位置+x. 然后在b+1的位置-x 树状 ...

  7. POJ 2155 Matrix(二维树状数组+区间更新单点求和)

    题意:给你一个n*n的全0矩阵,每次有两个操作: C x1 y1 x2 y2:将(x1,y1)到(x2,y2)的矩阵全部值求反 Q x y:求出(x,y)位置的值 树状数组标准是求单点更新区间求和,但 ...

  8. hdu-3584 Cube---三维树状数组+区域更新单点查询

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1.A[i,j,k]表示集合中第 i ...

  9. POJ-2155 Matrix---二维树状数组+区域更新单点查询

    题目链接: https://vjudge.net/problem/POJ-2155 题目大意: 给一个n*n的01矩阵,然后有两种操作(m次)C x1 y1 x2 y2是把这个小矩形内所有数字异或一遍 ...

随机推荐

  1. Vigenère 密码(luogu 1079)

    题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南 ...

  2. (九)STM32之AFIO

    也许你以为IO和AFIO是很简单的,事实上有几个误区可能很多人都没注意过,当你只用现成的开发板来学习的时候,别人已经帮你做好了资源分配,所有的外设功能学习都是照着别人给你的例程去做的,这才没让你觉得奇 ...

  3. python实现简单爬虫抓取图片

    最近在学习python,正如大家所知,python在网络爬虫方面有着广泛的应用,下面是一个利用python程序抓取网络图片的简单程序,可以批量下载一个网站更新的图片,其中使用了代理IP的技术. imp ...

  4. CentOS 6.5 下安装 Kibana5

    1. 导入Elastic PGP Key 执行命令 rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 2. 安装Kiban ...

  5. oracle 执行计划详解

    简介:     本文全面详细介绍oracle执行计划的相关的概念,访问数据的存取方法,表之间的连接等内容.     并有总结和概述,便于理解与记忆! +++ 目录 ---     一.相关的概念    ...

  6. 微信公众平台网页获取用户OpenID方法

    下面我们一起来看看关于微信公众平台网页获取用户OpenID方法,有需要了解的朋友可以一起来看看吧.用户点击微信自定义菜单view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值 (即网页链接 ...

  7. mvc-3模型和数据(2)

    寻址引用 源代码现存的问题:当保存或通过find()查找记录时,所返回的实例并没有复制一份,因此对任何属性的修改都会影响原始资源:这里我们只想当调用update()方法时才会修改资源 //由于Mode ...

  8. jquery优化02

    缓存变量:DOM遍历是昂贵的,所以尽量将会重用的元素缓存. $element = $('#element'); h = $element.height(); //缓存 $element.css('he ...

  9. PDA手持终端实现零售行业商场和超市仓储管理和销售开单自动化和系统化

    近几年,连锁药店得到了迅速扩张,由于药品种类过于繁杂.客户分散票据过多,急剧扩张之后的连锁药店企业在信息流处理上遇到了各种各样的问题 到现在已经有3000多家连锁药房,需要采购的正规药品就有数万个品种 ...

  10. windows 8 系统部署IIS并发布网站

    企业用户可以在已经部署了windows 8 的电脑中通过部署IIS服务器来发布自己公司的企业内部网站实现对企业的网络办公的管理工作. 准备篇 IIS的添加和运行 一.IIS的添加 1.请进入“控制面板 ...