教主的游乐场
作者:互联网
教主的游乐场
时间限制: 1 Sec 内存限制: 128 MB题目描述
Orz教主的成员为教主建了一个游乐场,在教主的规划下,游乐场有一排n个弹性无敌的跳跃装置,它们都朝着一个方向,对着一个巨大的湖,当人踩上去装置可以带你去这个方向无限远的地方,享受飞行的乐趣。但是等这批装置投入使用时,却发现来玩的人们更喜欢在这些装置上跳来跳去,并且由于这些装置弹性的优势,不但它们能让人向所对的方向能跳很远,也都能向相反方向跳一定的距离。于是教主想出了个游戏,这n个装置按朝向相反的方向顺序以1..n编号。第i个装置可以跳到1..i-1个装置,且每个装置有一个不一定相同的反方向弹性a[i],代表第i个装置还可以跳到第i+1..i+a[i]个装置。教主指定一个起始的装置,问从这个装置开始,最少需要连续踩几次装置(起始的装置也算在内),可以跳到第n个装置的后方,即若第k个装置有k+a[i]>n,那么从第k个装置就可以跳到第n个装置的后方。
(PS:你可以认为有n+1个装置,即需要求多少次能条到第n+1个装置)
输入
输入的第1行包含两个正整数n,m,为装置的数目以及询问的次数。第2行包含n个正整数,第i个正整数为a[i],即第i个装置向反方向最大跳跃的长度。
第3行包含了m个正整数,为询问从哪一个装置开始,最少要几次跳到第n个的后方。
数字之间用空格隔开。
输出
输出包含1行,这一行有m个正整数,对于每一个询问,输出最少需要踩的装置数,数字之间用空格隔开。行末换行且没有多余的空格。
样例输入
5 5 2 4 1 1 1 1 2 3 4 5
样例输出
2 1 2 2 1
提示
若从第1个装置开始则跳到第2个装置,接着就可以跳到第n个装置的后方。若从第3个装置开始则同样跳到第2个装置。
若从第4个装置开始可以跳到第2个装置或最后一个装置,接着跳出第n个装置,答案同样为2。
【数据规模】
对于20%的数据,有n≤10;
对于40%的数据,有n≤100,m≤10;
对于60%的数据,有n≤1000,a[i]≤1000,m≤500;
对于100%的数据,有n≤100000,a[i]≤n,m≤50000。
题解
线段树+DP,是我太笨还是这题就这样做?种一颗每个结点都是极大值的树,能一次跳出n的其结点值更新为1,先从n到1遍历一次(向后跳),找每个点i到i+a[i]中的最小值,然后用来更新i的结点的值;
再从1到n遍历一次(向前跳),找1到i的最小值,然后用来更新i的结点的值,这样就求出每个点跳出n所需的最小步数啦。
1 #include<cstdio> 2 #include<iostream> 3 #define INF 0x7fffffff 4 using namespace std; 5 const int N = 100009; 6 int t[4*N]; 7 int n, m, a[N]; 8 void build(int L, int R, int rt) 9 { 10 t[rt] = INF; 11 if(L >= R) return; 12 int lc = rt << 1; 13 int rc = rt << 1 | 1; 14 int mid = (L + R) >> 1; 15 build(L, mid, lc); 16 build(mid+1, R, rc); 17 return; 18 } 19 void update(int L, int R, int rt, int to, int val) 20 { 21 if(R < to || L > to || L > R) return; 22 if(L == R) 23 { 24 t[rt] = min(t[rt], val); 25 return; 26 } 27 int lc = rt << 1; 28 int rc = rt << 1 | 1; 29 int mid = (L + R) >> 1; 30 if(mid >= to) update(L, mid, lc, to, val); 31 else update(mid+1, R, rc, to, val); 32 t[rt] = min(t[lc], t[rc]); 33 return; 34 } 35 int query(int L, int R, int rt, int l, int r) 36 { 37 if(R < l || L > r || L > R) return INF; 38 if(l <= L && R <= r) return t[rt]; 39 int lc = rt << 1; 40 int rc = rt << 1 | 1; 41 int mid = (L + R) >> 1; 42 int lv = query(L, mid, lc, l, r); 43 int rv = query(mid+1, R, rc, l, r); 44 t[rt] = min(t[lc], t[rc]); 45 return min(lv, rv); 46 } 47 int main() 48 { 49 scanf("%d%d", &n, &m); 50 build(1, n, 1); 51 for(int i = 1; i <= n; i++) 52 { 53 scanf("%d", &a[i]); 54 if(i + a[i] > n) 55 update(1, n, 1, i, 1); 56 } 57 for(int i = n; i > 0; i--) 58 { 59 int r = min(n, i+a[i]); 60 int f = query(1, n, 1, i, r); 61 update(1, n, 1, i, f+1); 62 } 63 for(int i = 1; i <= n; i++) 64 { 65 int f = query(1, n, 1, 1, i); 66 update(1, n, 1, i, f+1); 67 } 68 for(int i = 1; i <= m; i++) 69 { 70 int x; 71 scanf("%d", &x); 72 int ans = query(1, n, 1, x, x); 73 printf("%d%c", ans, i==m?'\n':' '); 74 //printf("%d\n",ans); 75 } 76 return 0; 77 }View Code
标签:rt,装置,return,lc,int,mid,游乐场,教主 来源: https://www.cnblogs.com/Jony-English/p/12520099.html