LOJ #6435. 「PKUSC2018」星际穿越(倍增)
题面
题解
**参考了 这位大佬的博客 **
这道题好恶心啊qwq~~
首先一定要认真阅读题目 !! 注意 \(l_i<r_i<x_i\) 这个条件 !!
所以它询问的就是向左走的最短路了 .
不难发现只有两种策略 , 要么一直向左走 ; 要么第一次向右走 , 然后一直向左走 .
并且到一个定点 \(x\) 的最短路长度 肯定是从右向左一段段递增的 .
为什么呢 ? 不难发现 如果向右走两次 , 那么只有一次是一定有效的 , 另外一次的 \(l_i\) 一定不会小于这次 .
向左走的话 , 每次就记下沿途的 \(l_i\) 的最小值 , 用这个去转移走 \(j\) 次时 \(l\) 的最小值就行了 . ( \(70pts\) 见我 \(LOJ\) 提交吧qwq .)
然后这样暴力做的话就是 \(O(n^2)\) 的复杂度 显然不行 .
考虑优化 , 发现这个是一段段的 且 有连续性 , 有一个神奇的倍增可以快速实现这个功能 .
令 \(f_{i, j}\) 为 \([i, n]\) 所有点走 \(2^j\) 次能到达的最左端点 .
\]
为什么要这样记呢 ? 因为这样可以同时统计第一次向右走可能产生的贡献 .
令 \(sum_{i,j}\) 为 \(i \to (i \sim f_{i,j})\) 中所有点走的步数之和 . 这个转移就很显然啦 .
\]
然后我们考虑走的时候算答案 . 因为我们一开始预处理只包括了可能向右走的情况 , 但直接第一步向左走的没有处理掉 .
此处我们单独处理第一步向左走的情况就行了 .
令 \(Calc(i, pos)\) 为 \(i \to [i, pos)\) 的所需步数之和 . 那么每次询问就能用差分来表示成 \(Calc(l,pos) - Calc(r + 1, pos)\) 了 .
然后倍增的时候类似于这样跳的 :

假设我们总共要经过的是 红色 那一段(其中 \(l_{pos}\) 已经跳完了) , 每次走的是 粉色 那一段 .
发现我们每次走的时候 , 要记下前面走了多少步数 , 然后给答案加上这一段的贡献 \(len \times tot\) .
最后有一小段多余的 蓝紫色 (因为每次 \(2^j\) 覆盖的是所有步数为这么多的 , 最后可能不满) 这段贡献就是 \(len \times (tot + 1)\) .
代码好像很短 ?
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(a) cout << #a << ": " << a << endl
using namespace std;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("6435.in", "r", stdin);
freopen ("6435.out", "w", stdout);
#endif
}
const int N = 3e5 + 1e3, inf = 0x3f3f3f3f;
int L[N], n, f[N][21], sum[N][21], Log2[N];
void Init() {
f[n + 1][0] = inf;
Fordown (i, n, 1)
f[i][0] = min(f[i + 1][0], L[i]), sum[i][0] = i - f[i][0];
For (j, 1, Log2[n]) For (i, 1, n) if (f[i][j - 1]) {
f[i][j] = f[f[i][j - 1]][j - 1];
sum[i][j] = sum[i][j - 1] + sum[f[i][j - 1]][j - 1] + ((f[i][j - 1] - f[i][j]) << (j - 1));
}
}
inline int Calc(int qp, int pos) {
if (L[pos] <= qp) return pos - qp;
int res = pos - L[pos]; pos = L[pos]; int tot = 1;
Fordown (i, Log2[pos], 0)
if (f[pos][i] > qp) res += sum[pos][i] + (pos - f[pos][i]) * tot, pos = f[pos][i], tot += 1 << i;
return res + (pos - qp) * (tot + 1);
}
int main () {
File();
n = read(); L[1] = 1; For (i, 2, n) L[i] = read(), Log2[i] = Log2[i >> 1] + 1; Init();
int m = read();
For (i, 1, m) {
int l = read(), r = read(), x = read();
int ans = Calc(l, x) - Calc(r + 1, x), len = r - l + 1, g = __gcd(ans, len);
printf ("%d/%d\n", ans / g, len / g);
}
return 0;
}
LOJ #6435. 「PKUSC2018」星际穿越(倍增)的更多相关文章
- LOJ 6435 「PKUSC2018」星际穿越——DP+倍增 / 思路+主席树
题目:https://loj.ac/problem/6435 题解:https://www.cnblogs.com/HocRiser/p/9166459.html 自己要怎样才能想到怎么做呢…… dp ...
- loj#6435. 「PKUSC2018」星际穿越(倍增)
题面 传送门 题解 我们先想想,在这个很特殊的图里该怎么走最短路 先设几个量,\(a_i\)表示\([a_i,i-1]\)之间的点都和\(i\)有边(即题中的\(l_i\)),\(l\)表示当前在计算 ...
- 【LOJ】#6435. 「PKUSC2018」星际穿越
题解 想出70的大众分之后就弃疗了,正解有点神仙 就是首先有个比较显然的结论,就是要么是一直往左走,要么是走一步右边,然后一直往左走 根据这个可以结合RMQ写个70分的暴力 我们就考虑,最优的话显然是 ...
- #6435. 「PKUSC2018」星际穿越
考场上写出了70分,现在填个坑 比较好写的70分是这样的:(我考场上写的贼复杂) 设\(L(i)=\min_{j=i}^nl(j)\) 那么从i开始向左走第一步能到达的就是\([l(i),i-1]\) ...
- 「PKUSC2018」星际穿越 (70分做法)
5371: [Pkusc2018]星际穿越 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 27 Solved: 11[Submit][Status] ...
- 「PKUSC2018」星际穿越(倍增)
倍增好题啊! 我们我们预处理 \(f[x][i]\) 表示 \(x\) 点最左到达的端点,\(sum[x][i]\) 表示 \(x\) 点最左到达的端点时 \(f[x][i]\sim x\) 的答案, ...
- 「PKUSC2018」星际穿越
传送门 Solution 倍增 Code #include <bits/stdc++.h> #define reg register #define ll long long usin ...
- LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)
题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...
- LOJ #6432. 「PKUSC2018」真实排名(组合数)
题面 LOJ #6432. 「PKUSC2018」真实排名 注意排名的定义 , 分数不小于他的选手数量 !!! 题解 有点坑的细节题 ... 思路很简单 , 把每个数分两种情况讨论一下了 . 假设它为 ...
随机推荐
- python 知识2
零. type()函数怎么使用 type()的使用方法:type(对象)type()是接收一个对象当做参考,之后反回对象的相应类型.>>>type(1)<type 'int'& ...
- Luogu2045 方格取数加强版(K取方格数) 费用流
题目传送门 题意:给出一个$N \times N$的方格,每个格子中有一个数字.你可以取$K$次数,每次取数从左上角的方格开始,每一次只能向右或向下走一格,走到右下角结束,沿路的方格中的数字将会被取出 ...
- 重装系统之win10不能进入bios界面
原因 自Win10发布以来,新出厂的预装Win10的电脑都默认在UEFI模式下启动操作系统.UEFI启动是一种新的主板引导项,正被看做是有近20多年历史的BIOS 的继任者.顾名思义,快速启动是可以提 ...
- BootStrap学习(4)_分页&标签&缩略图&警告&进度条
一.分页 分页(Pagination),是一种无序列表,Bootstrap 像处理其他界面元素一样处理分页. .pagination --添加该 class 来在页面上显示分页. .disa ...
- 商场促销-策略模式(和简单工厂模式很像的哇) C#
还是那几句话: 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 废话不多说,直接进入正题: 首先按照大话设计模式的解释,在这里也总结下策略模式 ...
- AutoMapper自动映射
十年河东,十年河西,莫欺少年穷. 学无止境,精益求精. 不扯犊子,直接进入正题: AutoMapper自动映射常用于EF中,能很好的解决DTO和Model之间相互映射的问题.在未使用AutoMappe ...
- Ubuntu 打包后安装提示:子进程 已安装 pre-removal 脚本 返回了错误号 1
子进程 已安装 pre-removal 脚本 返回了错误号 1或2 与 子进程 已安装 post-installation 脚本 返回了错误号 1或2 一.子进程 已安装 pre-removal ...
- TCP服务端开发为例--web开发不同url请求为何会走不同方法
拿java的web开发为例子,相信有很多小伙伴是做j2EE开发的,htpp请求,json数据传输都是工作中经常用的,查询请求,添加请求,修改请求前端配个url,例如https://localhost/ ...
- Git push 时如何避免出现 "Merge branch 'master' of ..."
在使用 Git 的进行代码版本控制的时候,往往会发现在 log 中出现 "Merge branch 'master' of ..." 这句话,如下图所示.日志中记录的一般为开发过程 ...
- ExtJs 编译
前台使用Extjs加载源码的话是非常庞大的,编译之后就只加载一个app.js文件.这种技能如果不知道的话怕别人骂我不是个女程序员.哈哈哈哈哈. 打开cmd,进入程序Extjs的文件夹,如我的程序Ext ...