题解

想出70的大众分之后就弃疗了,正解有点神仙

就是首先有个比较显然的结论,就是要么是一直往左走,要么是走一步右边,然后一直往左走

根据这个可以结合RMQ写个70分的暴力

我们就考虑,最优的话显然是走一步左边就到了目标点,第二步才开始有分叉

假如我们先走了一步左边,然后就变成了,从\(L[x]\)开始走,下一步可以走到\([L[x],N]\)的所有点最小的转移点之前,之后再把后来走的点代价都加上1即可

这样的话,不管是一直走左边,还是走了一步右边再走了左边,情况都被包含了

这个时候考虑这个问题就比较简单了,可以使用倍增

\(f[i][j]\)表示\([i,n]\)内最小的\(l[x]\)的值

\(s[i][j]\)表示\(i\)走到\(f[i][j]\)内所有点的距离和

转移就是

\(f[i][j] = f[f[i][j - 1]][j - 1]\)

\(s[i][j] = s[i][j - 1] + s[f[i][j - 1]][j - 1] + 2^{j - 1} * (f[i][j - 1] - f[i][j])\)

查询两端前缀和,查的时候直接把\(x\)变成\(L[x]\)进行倍增即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 300005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,L[MAXN];
int f[MAXN][20];
int64 s[MAXN][20];
void Init() {
read(N);
for(int i = 2 ; i <= N ; ++i) read(L[i]);
f[N][0] = L[N];s[N][0] = N - L[N];
for(int i = N - 1 ; i >= 1 ; --i) {
f[i][0] = min(f[i + 1][0],L[i]);s[i][0] = i - f[i][0];
}
for(int j = 1 ; j <= 19 ; ++j) {
for(int i = 1 ; i <= N ; ++i) {
f[i][j] = f[f[i][j - 1]][j - 1];
s[i][j] = s[i][j - 1] + s[f[i][j - 1]][j - 1] + 1LL * (f[i][j - 1] - f[i][j]) * (1 << j - 1);
}
}
}
int64 gcd(int64 a,int64 b) {
return b == 0 ? a : gcd(b,a % b);
}
int64 Calc(int tar,int st) {
if(tar >= L[st]) return st - tar;
int64 res = st - L[st];st = L[st];
int64 sum = 1;
for(int j = 19 ; j >= 0 ; --j) {
if(f[st][j] >= tar) {
res += s[st][j];
res += 1LL * sum * (st - f[st][j]);
st = f[st][j];
sum += 1 << j;
}
}
res += 1LL * (sum + 1) * (st - tar);
return res;
}
void Solve() {
int Q;int l,r,x;
read(Q);
while(Q--) {
read(l);read(r);read(x);
int64 u = Calc(l,x) - Calc(r + 1,x),d = r - l + 1,g = gcd(u,d);
u /= g;d /= g;
out(u);putchar('/');out(d);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}

【LOJ】#6435. 「PKUSC2018」星际穿越的更多相关文章

  1. LOJ #6435. 「PKUSC2018」星际穿越(倍增)

    题面 LOJ#6435. 「PKUSC2018」星际穿越 题解 参考了 这位大佬的博客 这道题好恶心啊qwq~~ 首先一定要认真阅读题目 !! 注意 \(l_i<r_i<x_i\) 这个条 ...

  2. LOJ 6435 「PKUSC2018」星际穿越——DP+倍增 / 思路+主席树

    题目:https://loj.ac/problem/6435 题解:https://www.cnblogs.com/HocRiser/p/9166459.html 自己要怎样才能想到怎么做呢…… dp ...

  3. loj#6435. 「PKUSC2018」星际穿越(倍增)

    题面 传送门 题解 我们先想想,在这个很特殊的图里该怎么走最短路 先设几个量,\(a_i\)表示\([a_i,i-1]\)之间的点都和\(i\)有边(即题中的\(l_i\)),\(l\)表示当前在计算 ...

  4. #6435. 「PKUSC2018」星际穿越

    考场上写出了70分,现在填个坑 比较好写的70分是这样的:(我考场上写的贼复杂) 设\(L(i)=\min_{j=i}^nl(j)\) 那么从i开始向左走第一步能到达的就是\([l(i),i-1]\) ...

  5. 「PKUSC2018」星际穿越 (70分做法)

    5371: [Pkusc2018]星际穿越 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 27  Solved: 11[Submit][Status] ...

  6. 「PKUSC2018」星际穿越(倍增)

    倍增好题啊! 我们我们预处理 \(f[x][i]\) 表示 \(x\) 点最左到达的端点,\(sum[x][i]\) 表示 \(x\) 点最左到达的端点时 \(f[x][i]\sim x\) 的答案, ...

  7. 「PKUSC2018」星际穿越

    传送门 Solution  倍增 Code  #include <bits/stdc++.h> #define reg register #define ll long long usin ...

  8. LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)

    题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...

  9. LOJ #6432. 「PKUSC2018」真实排名(组合数)

    题面 LOJ #6432. 「PKUSC2018」真实排名 注意排名的定义 , 分数不小于他的选手数量 !!! 题解 有点坑的细节题 ... 思路很简单 , 把每个数分两种情况讨论一下了 . 假设它为 ...

随机推荐

  1. bzoj1178/luogu3626 会议中心 (倍增+STL::set)

    贪心地,可以建出一棵树,每个区间对应一个点,它的父亲是它右边的.与它不相交的.右端点最小的区间. 为了方便,再加入一个[0,0]区间 于是就可以倍增来做出从某个区间开始,一直到某个右界,这之中最多能选 ...

  2. Spring Boot整合MyBatis(使用Spring Tool Suite工具)

    1. 创建Spring Boot项目 通过Spring Tool Suite的Spring Starter Project对话框,其实是把项目生成的工作委托http://start.spring.io ...

  3. C++代理模式

    主要根据代理模式整理,感谢作者分享! [DP]上的定义:为其他对象提供一种代理以控制对这个对象的访问.有四种常用的情况:(1)远程代理,(2)虚代理,(3)保护代理,(4)智能引用.本文主要介绍虚代理 ...

  4. Python3:if __name__ == '__main__' 详解

    一般在风格比较好的代码中会有一行if __name__ == '__main__' :代码,这里说明一下这句代码的用处,先上两个代码test1.py和test2.py: # test1.py prin ...

  5. Go 语言编程规范

    1. gofmt 命令 大部分的格式问题可以通过 gofmt 来解决,gofmt 自动格式化代码,保证所有的 go 代码与官方推荐的格式保持一致,所有格式有关问题,都以gofmt的结果为准.所以,建议 ...

  6. Vue实例的生命周期(钩子函数)

    Vue实例的生命钩子总共有10个 先上官方图: 下面时一个vue实例定义钩子函数的例子: var app=new Vue({ el:'#app', beforeCreate:function(){ c ...

  7. 了解Linux操作系统的引导过程

    原文地址:http://os.51cto.com/art/200706/49690.htm 1.简介 Linux启动过程指的是从加电到看到shell提示的这一段时间. Linux启动的过程可以大概分为 ...

  8. Codeforces 906 D. Power Tower

    http://codeforces.com/contest/906/problem/D 欧拉降幂 #include<cstdio> #include<iostream> usi ...

  9. HDU 1524 树上无环博弈 暴力SG

    一个拓扑结构的图,给定n个棋的位置,每次可以沿边走,不能操作者输. 已经给出了拓扑图了,对于每个棋子找一遍SG最后SG和就行了. /** @Date : 2017-10-13 20:08:45 * @ ...

  10. 学了display:flex垂直居中容易多了

    以前div内部的文字垂直居中,使用height = line-height,现在可以使用display:flex来实现了 .div{ display:flex; align-items:center; ...