PKUSC 2018 星际穿越
这是一道有难度的倍增题。
因为可以直接计算,故只要求出,就可以回答询问了。
我们设表示从出发,走步之内最远能到达哪些点。
接下来我们证明一个结论:,
首先我们发现,最优的路径一定是从出发,向后走最多一格,然后再一直向前走。
显然走了一步,那么只能往前走,。
考虑走了超过一步,那么我们可以在第一步走到一些的点,还有一些点,虽然大于,但是,导致间没有边相连,无法在第一步走到。但是我们仍然可以加入这些点,因为这些点都满足,而,故肯定小于,这些并不会对后缀造成影响。
这样设,那么我们可以从连一条边到,表示在下一步最远可以到达。
我们将问题转化成表示从出发,走到的每个点的最短路的和,那么。
这样,我们可以一步一步找下一个,同时进行计算,是的。
但是,我们发现这个问题可以用倍增,设表示从出发,走步最远可以到达的点,则。
然后设,则不难推出。
进行函数的过程和预处理倍增的过程基本类似。
要特别注意两点:
- 最后一步要特判,因为有可能直接跳过了我们规定的最小值。
- 第一步也要特判,因为按照我们的推导,,但实际上应该是,因为此时我们还无法到大于的点上。
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
using ll=long long;
const int maxn=300005;
const int maxlog=20;
int n,q,l[maxn],minl[maxn];
int nxt[maxn][maxlog];
ll sum[maxn][maxlog];
ll gcd(ll a,ll b) {
return b==0?a:gcd(b,a%b);
}
ll solve(ll to,ll pos) {
if(to==pos) return 0;
ll ret=0,tot=0;
if(l[pos]>=to) ret+=pos-l[pos],tot=1,pos=l[pos];
for(int j=maxlog-1;~j;j--) {
if(nxt[pos][j]>=to) {
ret+=sum[pos][j]+tot*(pos-nxt[pos][j]);
pos=nxt[pos][j];
tot+=1ll<<(ll)j;
}
}
ret+=(pos-to)*(tot+1);
return ret;
}
int main() {
scanf("%d",&n);
for(int i=2;i<=n;i++)
scanf("%d",&l[i]);
minl[n]=l[n];
for(int i=n-1;i>=2;i--)
minl[i]=std::min(l[i],minl[i+1]);
for(int i=1;i<=n;i++) {
nxt[i][0]=minl[i]; sum[i][0]=i-minl[i];
for(int j=1;j<maxlog;j++) {
nxt[i][j]=nxt[nxt[i][j-1]][j-1];
sum[i][j]=sum[i][j-1]+sum[nxt[i][j-1]][j-1]+(1ll<<ll(j-1))*(nxt[i][j-1]-nxt[i][j]);
}
}
for(int i=1;i<=n;i++) {
for(int j=0;j<maxlog;j++) {
if(!nxt[i][j]) sum[i][j]=0;
}
}
scanf("%d",&q);
while(q--) {
int lef,rig,x;
scanf("%d%d%d",&lef,&rig,&x);
ll a=solve(lef,x)-solve(rig+1,x),b=rig-lef+1,c=gcd(a,b);
printf("%lld/%lld\n",a/c,b/c);
}
return 0;
}
标签:
Data Structure
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话