zoukankan      html  css  js  c++  java
  • NOJ/HUST 1095 校赛 Just Go 线段树模板题

    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,但是需要转移的数是一个区间,后来想到因为修改的是一个区间的值,想到用树状数组,但是区间修改的操作好像很烦阿
       最终被告知是线段树。
      1 #include <stdio.h>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <string.h>
      5 #define nods(x) tree[x]
      6 #define lefs(x) tree[x << 1]
      7 #define rigs(x) tree[x << 1 | 1]
      8 using namespace std;
      9  
     10 const int INF = 0x3f3f3f3f;
     11 const int MAX = 100010;
     12 const int MOD = 1e9 + 7;
     13  
     14 struct segtree
     15 {
     16     int l, r, ans; //区间范围
     17     int add;       //懒惰标记
     18 }tree[MAX << 2];
     19  
     20 //单点修改
     21 void change(int &bep, int val)
     22 {
     23     bep += val;
     24     bep = (bep % MOD + MOD) % MOD;
     25 }
     26  //父节点更新
     27 void pushup(int pos)
     28 {
     29     change(nods(pos).ans, lefs(pos).ans + rigs(pos).ans);
     30 }
     31  //构造线段树
     32 void build(int p, int l, int r)
     33 {
     34     nods(p).l = l;
     35     nods(p).r = r;
     36     nods(p).ans = nods(p).add = 0;
     37     if(l == r && l == 1)
     38         nods(p).ans = 1;
     39     if(l == r)
     40         return ;
     41  
     42     int mid = (l + r) >> 1;
     43     build( p << 1, l, mid  );
     44     build( p << 1 | 1, mid + 1, r);
     45     pushup(p);
     46 }
     47  //向下更新叶 通过延迟标记更新
     48 void pushdown(int p)
     49 {
     50     if(nods(p).add)
     51     {
     52         change(lefs(p).add, nods(p).add);
     53         change(rigs(p).add, nods(p).add);
     54         change(lefs(p).ans, nods(p).add);
     55         change(rigs(p).ans, nods(p).add);
     56         nods(p).add = 0;
     57     }
     58 }
     59 //询问
     60 int query(int p, int bor)
     61 {
     62     if(nods(p).l == nods(p).r)//递归到最小叶,直接返回
     63         return nods(p).ans; 
     64     pushdown(p);              //先应用标记 再查询
     65  
     66     int mid = (nods(p).l + nods(p).r) >> 1;
     67     if(bor <= mid)             
     68         return query(p << 1, bor);        //查询下一层左儿子
     69     else return query(p << 1 | 1, bor);   //查询下一层右儿子
     70 }
     71  //区间修改
     72 void update(int p, int l, int r, int val)
     73 {
     74     if(nods(p).l >= l && nods(p).r <= r) //完全包含
     75     {
     76         change(nods(p).add, val);        //延迟标记
     77         change(nods(p).ans, val);        //更新该点
     78         return ;
     79     }
     80     pushdown(p);                         //向下更新
     81     int mid = (nods(p).l + nods(p).r) >> 1;
     82     if(r <= mid)                         //[l,r] 被包含于 [pl,mid]
     83         update(p << 1, l, r , val);
     84     else if(l > mid)                     //[l,r] 被包含于 [mid,pr]
     85         update(p << 1 | 1, l, r, val);
     86     else                                 //中间截断
     87     {
     88         update(p << 1, l, mid, val);
     89         update(p << 1 | 1,1 + mid, r, val);
     90     }
     91     pushup(p);
     92 }
     93  
     94  
     95 int main()
     96 {
     97     int T, t;
     98     int ans, ss, ee, n;
     99     cin >> T;
    100     while(T--)
    101     {
    102         scanf("%d", &n);
    103         build(1, 1, n);
    104         for(int i = 1; i <= n; i++)
    105         {
    106             scanf("%d", &t);
    107             ss = i + 1;
    108             ee = min(i+t, n);
    109             ans = query(1, i);
    110             if(i!=n)
    111                 update(1, ss, ee, ans);
    112         }
    113         printf("%d
    ", query(1, n));
    114     }
    115 }


  • 相关阅读:
    软工结对作业
    软工个人博客作业-软件案例分析
    软工个人项目作业
    软工个人博客作业
    软工第一次个人作业
    2019OO第三单元作业总结
    2019OO第二单元作业总结
    提问回顾以及个人总结
    软工结对项目——图形交点PLUS
    个人博客作业-软件案例分析
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/5500780.html
Copyright © 2011-2022 走看看