【题目大意】

有$n$个位置,每个位置有一个数$x_i$,代表从$i$经过1步可以到达的点在$[\max(1, i-x_i), \min(i+x_i, n)]$中。

定义$(i,j)$的距离表示从$i$到$j$经过多少步,从$j$到$i$经过多少步,这两个取最小值。

求任意两点间最大的距离。

$1\leq n \leq 10^5, 1 \leq x_i < n$

【题解】

每个点经过若干次能过到达的,显然是一个区间。

考虑倍增,$[L_{x,i}, R_{x,i}]$表示从$x$开始,经过$2^i$步,到达的区间。

这个可以通过倍增+线段树来解决,线段树维护最小值和最大值,对应区间两个端点。

对于询问,我们二分答案后,问题转化与是否能找出一个点对步数$> x$($x$为我们二分的值)

通过倍增我们可以求出每个点经过$x$步后到达的区间,设为$[L', R']$。那么不能到达的就是$[1, L']$和$[R',n]$。

问题转化为,$[1, L']$和$[R', n]$是否可以经过$x$步以内到达$i$这个点。

这个可以通过记录一个前缀和以及一个后缀和来解决。

这里的“和”指的是区间交。

然后就行啦!

时间复杂度$O(nlog^3n)$

upd: 线段树有点问题,已经修正

=========================分割线=============================

upd: 之前的复杂度有点问题,是$O(nlog^3n)$的,理论上是过不去的,但是常数太优秀了(逃

我们可以把二分改为从高位往低位确定答案的每位,每次就不需要倍增了,就在之前的基础上,直接做即可。这样就是$O(nlog^2n)$的了

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; const int N = 1e5 + , M = 2e5 + ;
const int inf = 1e9; # define bit(x, i) (((x) >> (i)) & ) int n;
struct pa {
int x, y;
pa() {}
pa(int x, int y) : x(x), y(y) {}
friend pa operator + (pa a, pa b) {
return pa(min(a.x, b.x), max(a.y, b.y));
}
friend pa operator - (pa a, pa b) {
return pa(max(a.x, b.x), min(a.y, b.y));
}
}; inline bool out(int x, pa t) {
return x < t.x || x > t.y;
} int L[][N], R[][N]; struct SMT {
pa w[M << ];
# define ls (x<<)
# define rs (x<<|)
inline void set(int n) {
for (int i=; i<=n+n; ++i) w[i] = pa(inf, -inf);
}
inline void build(int x, int l, int r, int p) {
if(l == r) {
w[x] = pa(L[p][l], R[p][l]);
return ;
}
int mid = l+r>>;
build(ls, l, mid, p);
build(rs, mid+, r, p);
w[x] = w[ls] + w[rs];
// printf("p = %d, [%d, %d], [%d, %d]\n", p, l, r, w[x].x, w[x].y);
}
inline pa query(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) return w[x];
int mid = l+r>>;
if(L > mid) return query(rs, mid+, r, L, R);
else if (R <= mid) return query(ls, l, mid, L, R);
else return query(ls, l, mid, L, mid) + query(rs, mid+, r, mid+, R);
}
# undef ls
# undef rs
}T[]; // have dis > x
pa c[N];
pa t[N];
pa f[N], g[N]; inline bool chk(int x) {
pa tmp;
for (int i=; i<=n; ++i) {
tmp.x = t[i].x, tmp.y = t[i].y;
tmp = T[x].query(, , n, tmp.x, tmp.y);
c[i] = tmp;
// printf(" i = %d, [%d, %d]\n", i, c[i].x, c[i].y);
}
f[] = c[]; g[n] = c[n];
for (int i=; i<=n; ++i) f[i] = f[i-] - c[i];
for (int i=n-; i; --i) g[i] = g[i+] - c[i];
for (int i=; i<=n; ++i) {
if(c[i].x == && c[i].y == n) continue;
// [1, c[i].x-1], [c[i].y+1], n]
if(c[i].x != ) {
if(out(i, f[c[i].x-])) return true;
}
if(c[i].y != n) {
if(out(i, g[c[i].y+])) return true;
}
}
return false;
}
// # include <time.h>
int main() {
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
cin >> n;
for (int i=; i<=; ++i) T[i].set(n);
for (int i=, x; i<=n; ++i) {
scanf("%d", &x);
L[][i] = max(i-x, );
R[][i] = min(i+x, n);
}
pa tem;
for (int j=; j<=; ++j) {
T[j-].build(, , n, j-);
for (int i=; i<=n; ++i) {
tem = T[j-].query(, , n, L[j-][i], R[j-][i]);
L[j][i] = tem.x, R[j][i] = tem.y;
}
}
T[].build(, , n, ); // for (int j=0; j<=5; ++j)
// for (int i=1; i<=n; ++i) printf("%d %d L = %d, R = %d\n", i, j, L[j][i], R[j][i]); int l = , r = n-, mid, ans = ;
for (int i=; i<=n; ++i) t[i] = pa(i, i);
for (int i=; ~i; --i) {
if(chk(i)) {
for (int j=; j<=n; ++j)
t[j] = c[j];
ans += (<<i);
}
} cout << ans + << endl;
// cerr << clock() << " ms\n";
return ;
}
/*
8
7 1 1 1 1 1 1 7 10
2 2 1 2 2 1 2 2 1 2
*/

下面是$O(nlog^3n)$的代码

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; const int N = 1e5 + , M = 2e5 + ;
const int inf = 1e9; # define bit(x, i) (((x) >> (i)) & ) int n;
struct pa {
int x, y;
pa() {}
pa(int x, int y) : x(x), y(y) {}
friend pa operator + (pa a, pa b) {
return pa(min(a.x, b.x), max(a.y, b.y));
}
friend pa operator - (pa a, pa b) {
return pa(max(a.x, b.x), min(a.y, b.y));
}
}; inline bool out(int x, pa t) {
return x < t.x || x > t.y;
} int L[][N], R[][N]; struct SMT {
pa w[M << ];
# define ls (x<<)
# define rs (x<<|)
inline void set(int n) {
for (int i=; i<=n+n; ++i) w[i] = pa(inf, -inf);
}
inline void build(int x, int l, int r, int p) {
if(l == r) {
w[x] = pa(L[p][l], R[p][l]);
return ;
}
int mid = l+r>>;
build(ls, l, mid, p);
build(rs, mid+, r, p);
w[x] = w[ls] + w[rs];
// printf("p = %d, [%d, %d], [%d, %d]\n", p, l, r, w[x].x, w[x].y);
}
inline pa query(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) return w[x];
int mid = l+r>>;
if(L > mid) return query(rs, mid+, r, L, R);
else if (R <= mid) return query(ls, l, mid, L, R);
else return query(ls, l, mid, L, mid) + query(rs, mid+, r, mid+, R);
}
# undef ls
# undef rs
}T[]; // have dis > x
pa c[N]; pa f[N], g[N]; inline bool chk(int x) {
// cout << "x = " << x << endl;
pa t;
for (int i=; i<=n; ++i) {
t.x = t.y = i;
for (int j=; ~j; --j)
if(bit(x, j)) t = T[j].query(, , n, t.x, t.y);
c[i] = t;
// printf(" i = %d, [%d, %d]\n", i, c[i].x, c[i].y);
}
f[] = c[]; g[n] = c[n];
for (int i=; i<=n; ++i) f[i] = f[i-] - c[i];
for (int i=n-; i; --i) g[i] = g[i+] - c[i];
for (int i=; i<=n; ++i) {
if(c[i].x == && c[i].y == n) continue;
// [1, c[i].x-1], [c[i].y+1], n]
if(c[i].x != ) {
if(out(i, f[c[i].x-])) return true;
}
if(c[i].y != n) {
if(out(i, g[c[i].y+])) return true;
}
}
return false;
}
// # include <time.h>
int main() {
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
cin >> n;
for (int i=; i<=; ++i) T[i].set(n);
for (int i=, x; i<=n; ++i) {
scanf("%d", &x);
L[][i] = max(i-x, );
R[][i] = min(i+x, n);
}
pa tem;
for (int j=; j<=; ++j) {
T[j-].build(, , n, j-);
for (int i=; i<=n; ++i) {
tem = T[j-].query(, , n, L[j-][i], R[j-][i]);
L[j][i] = tem.x, R[j][i] = tem.y;
}
}
T[].build(, , n, ); // for (int j=0; j<=5; ++j)
// for (int i=1; i<=n; ++i) printf("%d %d L = %d, R = %d\n", i, j, L[j][i], R[j][i]); int l = , r = n-, mid, ans;
while() {
if(r-l <= ) {
for (int i=r; i>=l; --i)
if(chk(i)) {
ans = i;
break;
}
break;
}
mid = l+r>>;
if(chk(mid)) l = mid;
else r = mid;
} cout << ans + << endl;
// cerr << clock() << " ms\n";
return ;
}
/*
8
7 1 1 1 1 1 1 7 10
2 2 1 2 2 1 2 2 1 2
*/

「6月雅礼集训 2017 Day11」jump的更多相关文章

  1. 「6月雅礼集训 2017 Day11」delight

    [题目大意] 有$n$天,每天能吃饭.睡觉.什么事也不干 每天吃饭的愉悦值为$e_i$,睡觉的愉悦值为$s_i$,什么都不干愉悦值为0. 要求每连续$k$天都要有至少$E$天吃饭,$S$天睡觉. 求最 ...

  2. 「6月雅礼集训 2017 Day11」tree

    [题目大意] 给出一棵带权树,有两类点,一类黑点,一类白点. 求切断黑点和白点间路径的最小代价. $n \leq 10^5$ [题解] 直接最小割能过..但是树形dp明显更好写 设$f_{x,0/1/ ...

  3. 「6月雅礼集训 2017 Day10」quote

    [题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. ...

  4. 「6月雅礼集训 2017 Day4」qyh(bzoj2687 交与并)

    原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2687 [题目大意] 给出若干区间,求一个区间的大于等于2的子集,使得 |区间并| 和 | ...

  5. 「6月雅礼集训 2017 Day10」perm(CodeForces 698F)

    [题目大意] 给出一个$n$个数的序列$\{a_n\}$,其中有些地方的数为0,要求你把这个序列填成一个1到$n$的排列,使得: $(a_i, a_j) = 1$,当且仅当$(i, j) = 1$.多 ...

  6. 「6月雅礼集训 2017 Day8」route

    [题目大意] 给出平面上$n$个点,求一条连接$n$个点的不相交的路径,使得转换的方向符合所给长度为$n-2$的字符串. $n \leq 5000$ [题解] 考虑取凸包上一点,然后如果下一个是‘R' ...

  7. 「6月雅礼集训 2017 Day8」gcd

    [题目大意] 定义times(a, b)表示用辗转相除计算a和b的最大公约数所需步骤. 那么有: 1. times(a, b) = times(b, a) 2. times(a, 0) = 0 3. ...

  8. 「6月雅礼集训 2017 Day8」infection

    [题目大意] 有$n$个人,每个人有一个初始位置$x_i$和一个速度$v_i$,你需要选择若干个人来感染一个傻逼病毒. 当两个人相遇(可以是正面和背面),傻逼病毒会传染,求经过无限大时间后,传染完所有 ...

  9. 「6月雅礼集训 2017 Day7」电报

    [题目大意] 有n个岛屿,第i个岛屿有有向发射站到第$p_i$个岛屿,改变到任意其他岛屿需要花费$c_i$的代价,求使得所有岛屿直接或间接联通的最小代价. $1 \leq n \leq 10^5, 1 ...

随机推荐

  1. Why is setTimeout(fn, 0) sometimes useful?

    http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful jquery validation s ...

  2. HttpServletRequest和HttpServletResponse实例

    先看一下web.xml文件配置: <?xml version="1.0" encoding="UTF-8"?> <web-app versio ...

  3. ACM 第十三天

    训练赛题目 题目地址:https://odzkskevi.qnssl.com/415c275cb0a15fcb4ede21b8cb5297de?v=1533963116   A题代码: #includ ...

  4. C#的垃圾回收

    C#中垃圾回收 GC.Collect();强制进行内存回收.

  5. C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  6. P3065 [USACO12DEC]第一!First!

    题目描述 Bessie has been playing with strings again. She found that by changing the order of the alphabe ...

  7. Unable to open connection to "Microsoft SQL Server, provider V1.0.5000.0 in framework

    解决办法:1 以管理员身份登陆2 找到ORACLE_HOME文件夹(D:\oracle\ora92),点右键,选属性——安全,在组或用户栏中选"Authenticated Users&quo ...

  8. usaco中遇到的问题

    numbers are integers with unique digits 意思是数字中的每一个数字都是不一样的& 让一个图成为强连通图只需添加max(出度为0,入度为0)的点,然后如果图 ...

  9. 洛谷4578 & LOJ2520:[FJOI2018]所罗门王的宝藏——题解

    https://www.luogu.org/problemnew/show/P4578 https://loj.ac/problem/2520 有点水的. 先转换成图论模型,即每个绿宝石,横坐标向纵坐 ...

  10. [Leetcode] Maximum depth of binary tree二叉树的最大深度

    Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...