Codeforces1491——C.Pekora and Trampoline(差分思维+树状数组)

简介: Codeforces1491——C.Pekora and Trampoline(差分思维+树状数组)

原题链接

There is a trampoline park with n trampolines in a line. The i-th of which has strength Si.


Pekora can jump on trampolines in multiple passes. She starts the pass by jumping on any trampoline of her choice.


If at the moment Pekora jumps on trampoline i, the trampoline will launch her to position i+Si, and Si will become equal to max(Si−1,1). In other words, Si will decrease by 1, except of the case Si=1, when Si will remain equal to 1.


If there is no trampoline in position i+Si, then this pass is over. Otherwise, Pekora will continue the pass by jumping from the trampoline at position i+Si by the same rule as above.


Pekora can’t stop jumping during the pass until she lands at the position larger than n (in which there is no trampoline). Poor Pekora!


Pekora is a naughty rabbit and wants to ruin the trampoline park by reducing all Si to 1. What is the minimum number of passes she needs to reduce all Si to 1?


Input

The first line contains a single integer t (1≤t≤500) — the number of test cases.


The first line of each test case contains a single integer n (1≤n≤5000) — the number of trampolines.


The second line of each test case contains n integers S1,S2,…,Sn (1≤Si≤109), where Si is the strength of the i-th trampoline.


It’s guaranteed that the sum of n over all test cases doesn’t exceed 5000.


Output

For each test case, output a single integer — the minimum number of passes Pekora needs to do to reduce all Si to 1.


Example

inputCopy

3

7

1 4 2 2 2 2 2

2

2 3

5

1 1 1 1 1

outputCopy

4

3

0

Note

For the first test case, here is an optimal series of passes Pekora can take. (The bolded numbers are the positions that Pekora jumps into during these passes.)


[1,4,2,2,2,2,2]

[1,4,1,2,1,2,1]

[1,3,1,2,1,1,1]

[1,2,1,2,1,1,1]

For the second test case, the optimal series of passes is show below.


[2,3]

[1,3]

[1,2]

For the third test case, all Si are already equal to 1.


题意:

20200401134307494.png

思路:

首先,贪心的考虑,从a i > 1 a_{i}>1ai>1的点起跳是最优的。

然后,考虑每个点的贡献。假设当前高度为a i a_{i}ai,那么从i点能够跳到后面的[ i + 1 , i + s i ] [i+1,i+s_{i}][i+1,i+si]。

我们可以确定的是,对[ i + 2 , i + s i ] [i+2,i+s_{i}][i+2,i+si]的贡献都为1,涉及到区间修改,最容易想到的就是差分。这样就可以计算出i点对该段区间的贡献了。关于对i+1的贡献,该部分为0,因为当i==1时,不会选择该点为起点 (从前面跳到i点再继续往后跳的情况在下文)。

假设t i t_{i}ti表示i点被前面的点经过多少次,分下面几种情况考虑:

1.如果t i − s i > 1 t_{i}-s_{i}>1ti−si>1的话,因为当高度为1时就不会减少了,所以对i点不会产生贡献,从高度为1的i点会跳到i+1点,剩下的就是对i+1的贡献。

2.如果t i − s i < 1 t_{i}-s_{i}<1t i−si<1,说明前面的点不能使得该点变为高度为1,要再从这个点起跳。

维护的操作用的树状数组,复杂度nlogn。

代码:

///#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PLL;
typedef pair<int, int>PII;
typedef pair<double, double>PDD;
#define I_int ll
inline ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a, ll b, ll p)
{
    ll res = 1;
    while(b)
    {
        if(b & 1)res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
const int inf = 0x3f3f3f3f;
#define PI acos(-1)
const double eps = 1e-8;
const int maxn = 2e5 + 7;
int n,a[maxn];
ll tr[maxn];
ll lowbit(ll x){
    return x&(-x);
}
void update(ll pos,ll val){
  while(pos<=n){
    tr[pos]+=val;
    pos+=lowbit(pos);
  }
}
ll qask(ll pos){
  ll res=0;
  while(pos){
    res+=tr[pos];
    pos-=lowbit(pos);
  }
  return res;
}
void solve(){
  n=read;
  memset(tr,0,sizeof tr);
  rep(i,1,n) a[i]=read;
  ll res=0;
  for(int i=1;i<=n;i++){
    int tmp=a[i]-qask(i);
    if(tmp>1) res+=tmp-1;///还要从这个点起跳使这个点变为1
    if(a[i]>1) update(i+2,1),update(i+a[i]+1,-1);///计算对后面点的贡献
    if(tmp<1){
      ///该点正好可以为1,考虑对i+1的影响
      update(i+1,1-tmp);update(i+2,tmp-1);
    }
  }
  printf("%lld\n",res);
}
int main()
{
  int T=read;
  while(T--) solve();
    return 0;
}


目录
相关文章
|
9月前
|
人工智能 算法
算法提高:组合数学| 容斥原理常见应用
容斥原理常见的问题如下。 (1) 篮球、羽毛球、网球三种运动,至少会一种的有22人,会篮球的有15人,会羽毛球的有17人,会网球的有12人,既会篮球又会羽毛球的有11人,既会羽毛球又会网球的有7人,既会篮球又会网球的有9人,那么三种运动都会的有多少人? (2) 《西游记》《三国演义》《红楼梦》三大名著,至少读过其中一本的有20人,读过《西游记》的有10人,读过《三国演义》的有12人,读过《红楼梦》的有15人,读过《西游记》《三国演义》的有8人,读过《三国演义》《红楼梦》的有9人,读过《西游记》《红楼梦》的有7人。问三本书全都读过的有多少人?
103 0
算法提高:组合数学| 容斥原理常见应用
|
6天前
|
人工智能
倍增LCA受到启发的一题
倍增LCA受到启发的一题
15 0
|
8月前
|
算法 Java 测试技术
LeetCode 周赛上分之旅 #46 经典二分答案与质因数分解
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
40 0
LeetCode 周赛上分之旅 #46 经典二分答案与质因数分解
|
9月前
|
机器学习/深度学习 算法
算法提高:组合数学| 卡特兰数的实现
卡特兰数列是组合数学中在各种计数问题中常出现的数列,其前几项为1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012…… 卡特兰数首先是由欧拉在计算对凸n边形的不同的对角三角形剖分的个数问题时得到的,即在一个凸n边形中,通过不相交于n边形内部的对角线,把n边形拆分成若干三角形,不同的拆分数用Hn表示,Hn即卡特兰数。
87 0
算法提高:组合数学| 卡特兰数的实现
|
12月前
|
存储 移动开发 算法
C++/PTA 关于深度优先搜索和逆序对的题应该不会很难吧这件事
背景知识 深度优先搜索与 DFS 序 深度优先搜索算法(DFS)是一种用于遍历或搜索树或图的算法。以下伪代码描述了在树 T 上进行深度优先搜索的过程
87 0
|
存储 算法 大数据
基础算法-高精度加法
为什么要使用高精度算法 C++ 每一个变量都有自己的类型,每个类型都有自己的存储长度范围。
|
机器学习/深度学习 算法
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
Codeforces987D(逆向思维多源BFS)
Codeforces987D(逆向思维多源BFS)
92 0
|
存储 算法
数学知识:高斯消元(一)
复习acwing算法基础课的内容,本篇为讲解数学知识:高斯消元,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
116 0
数学知识:高斯消元(一)