[Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)

题面

n个点的图,点i和[l[i],i)的所有点连双向边。每次询问(l,r,x)表示x到[l,r]的所有点的最短路径长度和/(r-l+1)。

\(n \leq 10^5,l_i<r_i<x_i\)

分析

有(du)趣(liu)的倍增问题。

观察到\(l_i<r_i<x_i\),也就是说我们要求往左走的最小距离。首先差分一下,设\(sum(x,i)\)表示\(x\)到\([i,x-1]\)的最短距离和。那么答案就是\(\frac{sum(x,l)-sum(x,r+1)}{r-l+1}\)

然后我们不要直接考虑到x的最短路,而是反过来考虑走k步可以到达哪些节点。

我们从x开始走1步,可以走到哪里呢?。可以跳到的编号最小的点为\(l_x\),而最大的点应该是\(rb(x)=\max(k) (l_k \leq x)\),因为只要\(l_k \leq x\), \(x\)与\(k\)之间就有一条边。因此第1步能到达的区间是\([l_x,rb(x)]\)

第2步呢?。根据上面的分析,应该是\(\min(l_i)(i \in [l_x,rb(x)])\).但是实际上可以简化为\(\min(l_i)(i \in [l_x,n])\).因为在\([rb(x),n]\)内的点,它们的\(l\)比x还大,自然也比\([l_x,rb(x)]\)内的点的\(l\)还大,对最小值没有任何影响。

因此,设走\(k(k>1)\)步可以到达的编号最小的点为\(a\),那么走\(k+1\)步能够到达的编号最小的点为\(\min(l_i)(i\in [a,n])\).这样就可以倍增优化。

设\(f[i][j]\)表示\([i,n]\)内节点走\(2^j\)步能够到达的编号最小的点。那么显然有:

\[f[i][0]=\min(l_k),k \in[i,n]\]

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

为了求答案,我们再维护一个和,\(g[i][j]\)表示\(i\)到\([f[i][j],i-1]\)内所有点的距离和。那么:

\(g[i][0]=i-f[i][0]\) (到\([f[i][0],i-1]\)中的每个点的距离都为1)

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

这是因为:到\([f[i][j-1],i-1]\)内的节点,距离和是\(g[i][j-1]\)。而到\([f[i][j],f[i][j-1]]\)内的节点的距离由两部分组成,一部分是各节点到\(f[i][j-1]\)的距离\(g[f[i][j-1]][j-1]\),另一部分是从\(f[i][j-1]\)到\(i\)的距离\(2^{j-1}\).因为一共有\((f[i][j-1]-f[i][j])\)个节点,所以要乘上\((f[i][j-1]-f[i][j])\)

查询的话就倍增的跳即可,注意一些细节,还是直接上代码吧.

int calc(int x,int l){ //sum(x,l),[l,x-1]内答案 if(a[x]<=l) return x-l;//只需走一次的情况,特判//第一次走的答案 int ans=x-a[x];//距离和int cnt=1;//走的次数x=a[x]; for(int i=log2n;i>=0;i--){if(f[x][i]>=l){ans+=g[x][i]+cnt*(x-f[x][i]);//,g[x][i]为当前这段的距离和,但是之前每个节点还跳了cnt步到x,因此要加上cnt*[f[x][i],x-1]cnt+=(1<<i);x=f[x][i];}}if(x>l) ans+=x-l+cnt*(x-l);//如果最后一步没跳满,加上f[x][i] return ans;
} 

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 300000
#define maxlogn 25
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);
}
int n,q;
int log2n;
int a[maxn+5];
int f[maxn+5][maxlogn+5];
int g[maxn+5][maxlogn+5];
int calc(int x,int l){ //[l,x-1]内答案 if(a[x]<=l) return x-l;//特判第一次跳 int ans=x-a[x];int cnt=1;x=a[x]; for(int i=log2n;i>=0;i--){if(f[x][i]>=l){ans+=g[x][i]+cnt*(x-f[x][i]);//[f[x][i],x-1]跳到x还需cnt步 cnt+=(1<<i);x=f[x][i];}}if(x>l) ans+=x-l+cnt*(x-l);//如果最后一步没跳满,加上f[x][i] return ans;
}
int main(){int l,r,x;scanf("%d",&n);log2n=log2(n)+1;a[1]=1;for(int i=2;i<=n;i++) scanf("%d",&a[i]);f[n][0]=a[n];for(int i=n-1;i>=1;i--){f[i][0]=min(f[i+1][0],a[i]);g[i][0]=i-f[i][0];}for(int j=1;j<=log2n;j++){for(int i=1;i<=n;i++){if(f[i][j-1]){f[i][j]=f[f[i][j-1]][j-1];g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1]+((f[i][j-1]-f[i][j])<<(j-1)); //[f[i][j],f[i][j-1]-1]内的点跳到j还需2^{j-1}步 }}}scanf("%d",&q);while(q--){scanf("%d %d %d",&l,&r,&x);int up=calc(x,l)-calc(x,r+1);int down=r-l+1;int g=gcd(up,down);up/=g;down/=g;printf("%d/%d\n",up,down);}
}

转载于:https://www.cnblogs.com/birchtree/p/11521717.html

[Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)相关推荐

  1. LOJ.6435.[PKUSC2018]星际穿越(倍增)

    LOJ BZOJ 参考这儿qwq. 首先询问都是求,向左走的最短路. \(f[i][j]\)表示从\(i\)走到\(j\)最少需要多少步.表示这样只会\(O(n^2\log n)\)的= =但是感觉能 ...

  2. 洛谷p5465 [PKUSC2018]星际穿越

    [洛谷p5465][PKUSC2018]星际穿越 题面 洛谷 题解 众所周知PKUSC的题大多都不可做,今天好不容易看到1个倍增水题(我猜当时应该全场切了). 我们设\(f[i][j]\)表示\(i\ ...

  3. LOJ6435 洛谷5465 「PKUSC2018」星际穿越 倍增

    题目链接: loj6435 洛谷5465 蒟蒻zyd:这不是大水题吗?看我写个O(nlog2n)O(nlog^2n)O(nlog2n)的诡异ST表卡卡常数跑过去 题目:输出区间距离和 蒟蒻zyd:(笑 ...

  4. LOJ6435 PKUSC2018 星际穿越

    这个题吧当时在考场只得了45分 然后70分的性质都分析到了 不知道为啥就是写萎蛋了 哎 当时还是too young too simple 看了一下julao们的博客这个题有两种做法 一个是比较费脑子的 ...

  5. LOJ6435 PKUSC2018星际穿越

    Problem loj Solution 一个显而易见的结论,对于一个xi,要到达1号节点的最优路径只有第一步可能往右走,后面的步必定是往左走. 那么我们可以dp出整个右边可以走到的最左边的位置mn[ ...

  6. 【题解】LuoGu5465: [PKUSC2018]星际穿越

    原题传送门 重要性质:对于某个点xxx,必定是xxx到[y,x)[y,x)[y,x)中所有点的距离为1,xxx到[z,y)[z,y)[z,y)中所有点距离为2-- (满足z<y<xz< ...

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

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

  8. 《星际穿越》初解析——一部空前绝后的史诗科学巨作

    http://movie.douban.com/review/7188759/ 星际穿越通篇没有一句多余的对白,也没有多余的一个镜头,169分钟超大信息量填满整部电影.这里我打算从两个方面去分析这部电 ...

  9. 星际穿越+降临+明日边缘?星际拓荒重新定义星际探索题材游戏

    丨重新定义星际探索题材游戏 当我们说起"星际探索游戏", 我们会想起精英:危险,会想起坎巴拉太空计划,会想起那个灾难开场但终于修好的无人深空,还有那个耗资几亿还没弄完的星际公民-- ...

最新文章

  1. 两位智源青年科学家榜上有名!2020青橙奖公布
  2. html进度条圆圈渐变色,HTML5 canvas带渐变色的圆形进度条动画
  3. winform/timer控件/权限设置/三级联动
  4. apache 网站跳转至同一页面(可用于当网站在备案时显示告示)
  5. SAP MM 库存初始化和批量扩充物料仓位
  6. 计算机作文点评,未来的电脑作文评语
  7. 转置矩阵使用T,Hermite矩阵、正交矩阵、酉矩阵、奇异矩阵、正规矩阵、幂等矩阵
  8. UA STAT687 线性模型II 最小二乘理论1 普通最小二乘法
  9. 元宵节没用智能名片在互联网发贺卡,那就OUT了
  10. 键盘鼠标录制哪个好用_视频录制不用慌!这4个免费软件随意挑,网友:电脑神器...
  11. eclipse jvm_一种与众不同的JVM语言:Eclipse Xtend(现在适用于Android)
  12. 不知明镜里,何处得秋霜
  13. 一条update语句更新多条sql记录
  14. 【Windows 11】系统安装修改版 Subsystem for Android 安卓子系统,并用 Magisk Root
  15. 程序员为什么不自己单干?
  16. 【Pandas】日期抽取.dt.weekday与.weekday()
  17. 一种全新的智能远程施工方案被提出——无线图传+远程控制方案
  18. 什么是 web 容器(如tomcat)
  19. PF9810、PF9811……功率谐波测试仪、智能电量测量仪
  20. 登陆新浪微博批量下载收藏内容[Python脚本实现]

热门文章

  1. 2016年,失望,开心,耐心,学习,梦想,领悟,惋惜,展望
  2. 什么是SD-WAN?
  3. 隐藏文件(密码解锁)
  4. Android菜鸟笔记-EditText相关知识整理
  5. sicily 6445. Triangle transformation
  6. android讨论功能,集成融云Android SDK实现在群聊/讨论组中@人的功能
  7. MATLAB App Designer —— 手撕代码学习总结
  8. 同1 python变量可以先后赋予不同类型的值_【判断题】同一Python变量可以先后赋予不同类型的值。...
  9. Azure Create a function app Review+Create栏没有create
  10. john爆破mysql数据库