[CF1523H]Hopping Around the Array

2024-03-16 22:58
文章标签 array around hopping cf1523h

本文主要是介绍[CF1523H]Hopping Around the Array,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Hopping Around the Array

题解

**卡常题。

我们可以先将删除一个格子的操作看成用代价 0 0 0跳过一个格子,跳到 x + a x x+a_{x} x+ax视作代价为 1 1 1的跳跃。

由于 k k k值较小,我们可以先设计一个dp,令 d p i , j , k dp_{i,j,k} dpi,j,k表示从点 i i i出发进行 j j j次代价为 1 1 1的跳跃与 k k k次代价为 0 0 0的跳跃所能到达的最远的。
很明显,如果我们要往下一次跳跃转移的话我们肯定会先找到 [ i , d p i , j , k ] [i,dp_{i,j,k}] [i,dpi,j,k]之间 a x + x a_{x}+x ax+x最大的点进行转移。
但它总的跳跃次数会特别大,时间复杂度 O ( ( n + q ) n k 2 ) O\left((n+q)n k^2\right) O((n+q)nk2),明显会T掉,空间也会爆掉,我们考虑如何优化。

我们可以通过倍增进行维护。
可以证明,它每次都会跳跃到 a x + x a_{x}+x ax+x最大的一个点。
因为在这一次跳跃中,没有点能比这个点在下一次跳得更远的点,而这个点可以使下一次的 a x + x a_{x}+x ax+x尽可能大,所以在相同的跳跃次数中,它一定可以使终点尽可能地远。
所以我们下一次转移只需要从 a x + x a_{x}+x ax+x最大的点转移过来即可,每个点的转移点都是固定的。
我们将原 d p dp dp的定义改成 d p i , j , k dp_{i,j,k} dpi,j,k表示从点 i i i出发,经过 2 j 2^j 2j次代价为 1 1 1的跳跃, k k k次代价为 0 0 0的跳跃所能到达的最远的点。
转移方程式容易得到,记 c a l c ( l , r ) calc(l,r) calc(l,r)表示区间 [ l , r ] [l,r] [l,r] a x + x a_{x}+x ax+x最大的点的 x x x
d p i , j , k + Δ = max ⁡ l = 0 k ( d p c a l c ( i , d p i , j − 1 , l ) , j − 1 , k − l ) + Δ dp_{i,j,k+\Delta}=\max_{l=0}^{k}(dp_{calc(i,dp_{i,j-1,l}),j-1,k-l})+\Delta dpi,j,k+Δ=l=0maxk(dpcalc(i,dpi,j1,l),j1,kl)+Δ

而我们从一个起点开始到一个终点的最小步数可以像倍增求 l c a lca lca一样求,从这个起点开始倍增。
我们设 A k A_{k} Ak表示在进行了 x x x次花费为 1 1 1的操作, k k k次花费为 0 0 0的操作后,我们能走到的最远点。
我们每要多走 2 j 2^j 2j步时有转移式:
A k = max ⁡ i = 0 k ( d p A i , j , k − i ) A_{k}=\max_{i=0}^{k}(dp_{A_{i},j,k-i}) Ak=i=0maxk(dpAi,j,ki)
我们像求 l c a lca lca一样,找到它最多走多少步不会超过终点,那之后再走一步就是走到终点的最小步数。

有了这种想法,我们很容易发现对于很多个的询问这种做法也是适用的,它单次询问的时间复杂度是较小的时间复杂度确实很小,但常数不小
于是我们只需要先处理出 d p dp dp数组,再对单个询问倍增求出答案即可。
对于 c a l c ( l , r ) calc(l,r) calc(l,r)函数,我们可以通过st表进行维护。

时间复杂度 O ( ( n + q ) k 2 l o g n ) O\left((n+q)k^2log\,n\right) O((n+q)k2logn)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 40005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int zero=500;
const LL jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int n,q,a[MAXN],st[MAXN][20],f[MAXN][35][20],lg[MAXN],A[35],tmp[35],B[35];
int Max(const int x,const int y){return x+a[x]>y+a[y]?x:y;}
inline int query(int l,int r){if(l>r)return 0;r=min(r,n);const int k=lg[r-l+1];return Max(st[l][k],st[r-(1<<k)+1][k]);}
signed main(){read(n);read(q);lg[1]=0;for(reg int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;for(reg int i=1;i<=n;i++)read(a[i]);for(reg int i=1;i<=n;i++)st[i][0]=i;for(reg int i=1;i<=lg[n];i++)for(reg int j=1;j<=n-(1<<i)+1;j++)st[j][i]=Max(st[j][i-1],st[j+(1<<i-1)][i-1]);for(reg int i=1;i<=n;i++)for(reg int j=0;j<=30;j++)f[i][j][0]=i+a[i]+j;for(reg int l=0;l<lg[n];l++)for(reg int i=1;i<=n;i++)for(reg int j=0;j<=30;j++){for(reg int k=0;j+k<=30;k++)f[i][j+k][l+1]=max(f[i][j+k][l+1],f[query(i,f[i][j][l])][k][l]);for(reg int k=0;j+k<=30;k++)f[i][j+k][l+1]=max(f[i][j][l+1]+k,f[i][j+k][l+1]);}for(reg int i=1;i<=q;i++){int l,r,k,minn=2;read(l);read(r);read(k);if(l==r){puts("0");continue;}if(l+a[l]+k>=r){puts("1");continue;}for(reg int j=0;j<=k;j++)A[j]=l+a[l]+j;for(reg int j=lg[r-l+1];j>=0;j--){for(reg int i1=0;i1<=k;i1++)tmp[i1]=A[i1],B[i1]=query(l,A[i1]);bool flag=0;for(reg int i1=0;i1<=k&&!flag;i1++)for(reg int i2=0;i1+i2<=k;i2++)if(f[B[i1]][i2][j]>tmp[i1+i2]){tmp[i1+i2]=f[B[i1]][i2][j];if(tmp[i1+i2]>=r){flag=1;break;}}if(flag)continue;minn+=(1<<j);for(reg int i1=0;i1<=k;i1++)A[i1]=tmp[i1];}print(minn);putchar('\n');}return 0;
}

谢谢!!!

这篇关于[CF1523H]Hopping Around the Array的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/817006

相关文章

【uva】11536-Smallest Sub-Array(区间移动问题)

一个区间移动的问题,1A了,感觉没什么好说的。。 13975926 11536 Smallest Sub-Array Accepted C++ 0.809 2014-08-01 11:00:20 #include<cstdio>#include<cstring>#include<iostream>using namespace std;#define INF 1 << 30

leetCode#448. Find All Numbers Disappeared in an Array

Description Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. Find all the elements of [1, n] inclusive that do not appear in this

做一个问卷考试,标准答案对比用户填写的答案,array_diff 进行差集比对

if( empty(array_diff($answer_mark, $answer)) && empty(array_diff( $answer,$answer_mark))){//用户答题正确}else{// 答题错误} 做一个问卷考试,标准答案对比用户填写的答案,array_diff  进行差集比对   如用户填写的答案变量为answer   标准答案为answer_mark

[LeetCode] 238. Product of Array Except Self

题:https://leetcode.com/problems/product-of-array-except-self/description/ 题目 Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all

[LeetCode] 215. Kth Largest Element in an Array

题:https://leetcode.com/problems/kth-largest-element-in-an-array/description/ 题目 Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not th

MyBatis - 使用foreach迭代List/Array的说明

在 MyBatis 中的 foreach 元素,主要用于迭代 集合数据 以动态生成执行语句;主要有 item、index、collection、open、separator、close 等属性 属性说明         collection:要迭代的数据集对象,必填项         item:迭代出的元素的别名,必填项         index:元素的序号(map时为k

LeetCode - 33. Search in Rotated Sorted Array

33. Search in Rotated Sorted Array  Problem's Link  ---------------------------------------------------------------------------- Mean:  给你一个数组,这个数组是由两个有序的数组拼接成的(无重复元素),在这个数组中查找元素k的下标. anal

[置顶]后缀数组(suffix array)详解

写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具。 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料。 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, 能够实现后缀树的很多功能而时间复杂度也不太逊色,并且,它比后缀树所占用的空间小很多。 可以说,在信息学竞赛中后缀数组比后缀树要更为实用! 因此在本文中笔者想介绍一下后缀数组的基本概念、构造

【CodeForces】266E More Queries to Array... 线段树

E. More Queries to Array... time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output You've got an array, consisting of n

c/c++: warning: ISO C90 forbids variable length array ‘a’

文章目录 介绍C99安全问题类似的alloca安全问题的防护 介绍 https://en.cppreference.com/w/c/language/array @item -Wvla @opindex Wvla @opindex Wno-vla Warn if a variable-length array is used in the code. @option{-Wno-v