热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

bzoj3073:[Pa2011]Journeys线段树建边优化

bzoj3073:[Pa2011]JourneysDescriptionSeter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了&#

bzoj3073: [Pa2011]Journeys


Description

Seter建造了一个很大的星球&#xff0c;他准备建造N个国家和无数双向道路。N个国家很快建造好了&#xff0c;用1..N编号&#xff0c;但是他发现道路实在太多了&#xff0c;他要一条条建简直是不可能的&#xff01;于是他以如下方式建造道路&#xff1a;(a,b),(c,d)表示&#xff0c;对于任意两个国家x,y&#xff0c;如果a<&#61;x<&#61;b,c<&#61;y<&#61;d&#xff0c;那么在xy之间建造一条道路。Seter保证一条道路不会修建两次&#xff0c;也保证不会有一个国家与自己之间有道路。
Seter好不容易建好了所有道路&#xff0c;他现在在位于P号的首都。Seter想知道P号国家到任意一个国家最少需要经过几条道路。当然&#xff0c;Seter保证P号国家能到任意一个国家。
注意&#xff1a;可能有重边

Input

第一行三个数N,M,P。N<&#61;500000,M<&#61;100000。
后M行&#xff0c;每行4个数A&#xff0c;B&#xff0c;C&#xff0c;D。1<&#61;A<&#61;B<&#61;N,1<&#61;C<&#61;D<&#61;N。

Output

N行&#xff0c;第i行表示P号国家到第i个国家最少需要经过几条路。显然第P行应该是0。

Sample Input

5 3 4
1 2 4 5
5 5 4 4
1 1 3 3

Sample Output

1
1
2
0
1

知识点&#xff1a;线段树建边优化

首先有一个朴素的建边方式&#xff08;其实一点也不朴素&#xff0c;我不会。。。其实是我太弱了&#xff09;就是对于a~b到c~d我们新建虚拟节点p1,p2p1,p2&#xff0c; a~b到p1p1连边权为0的&#xff0c;然后p1p1p2p2连边权为1的&#xff0c;p2p2到c~d连边权为0的&#xff0c;然后反过来再建一遍。这样的话时间和空间的复杂度是O(mn2)O(mn2)不可以接受。
这个时候有一种神奇的操作叫做线段树建边优化。
考虑由于每次建边都是一整段区间&#xff0c;由此联想到线段树的区间修改&#xff0c;构造性地建线段树A和线段树B&#xff0c;分别表示线段树的出和入。操作如下&#xff1a;

  1. A树每个节点向父亲连边&#xff0c;B树每个节点向儿子连边。边权为零。
  2. 每个B树的叶子节点向对应的A树的叶子节点连边。
  3. 对于a~b连向c~d&#xff0c;在A树上找到a~b对应的区间u1,u2unu1,u2……un&#xff0c;将其连向虚拟节点p1p1&#xff0c;边权为0
  4. 虚拟节点p1p1到虚拟节点p2p2连上边权为1的边
  5. 在B树上找到c~d对应的区间v1,v2vnv1,v2……vnp2p2连到这些区间&#xff0c;边权为0

出线段树上的叶子节点对应的就是图上的真实节点。
然后跑一遍Dij堆优化即可。正确性。。。自己yy吧。因为每一条路径都代表了一种实际上的建边方式&#xff0c;可以自己画图。
空间复杂度&#xff1a;线段树节点是线性O(n)O(n)的&#xff0c;每一次连边最多连lognlogn个区间&#xff0c;一共连m次&#xff0c;所以总复杂度是O(mlogn&#43;n)O(mlogn&#43;n)时间复杂度一样样的。
但实际上是O(玄学)因为常数爆炸

代码

跑的速度和空间大小都是中等&#xff0c;模板题。

/**************************************************************Problem: 3073User: 2014lvzelongLanguage: C&#43;&#43;Result: AcceptedTime:9560 msMemory:340696 kb
****************************************************************/
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N &#61; 4400000;
const int M &#61; 21000000;
const int inf &#61; 0x3f3f3f3f;
int read() {char ch &#61; getchar(); int x &#61; 0, f &#61; 1;while(ch <&#39;0&#39; || ch > &#39;9&#39;) {if(ch &#61;&#61; &#39;-&#39;) f &#61; -1; ch &#61; getchar();}while(ch >&#61; &#39;0&#39; && ch <&#61; &#39;9&#39;) {x &#61; (x <<1) &#43; (x <<3) &#43; ch - &#39;0&#39;; ch &#61; getchar();}return x * f;
}
int pre[N], to[M], nxt[M], w[M], ls[N], rs[N], pos[N], dis[N], sz, top, ra, rb, n, m, s;
bool vis[N];
void add(int u, int v, int ww &#61; 0) {to[&#43;&#43;top] &#61; v; nxt[top] &#61; pre[u]; pre[u] &#61; top; w[top] &#61; ww;}
struct data {int a, b;data(int aa &#61; 0, int bb &#61; 0) : a(aa), b(bb) {}bool operator <(data a) const {return b > a.b;}
};void Build(int &p, int L, int R, bool flag) {if(!p) p &#61; &#43;&#43;sz;if(L &#61;&#61; R) {if(flag) pos[L] &#61; sz; return;}int mid &#61; L &#43; R >> 1;Build(ls[p], L, mid, flag); Build(rs[p], mid &#43; 1, R, flag);if(flag) add(ls[p], p), add(rs[p], p);else add(p, ls[p]), add(p, rs[p]);
}
void Add(int pa, int pb, int L, int R) {if(L &#61;&#61; R) {add(pb, pa); return;}int mid &#61; L &#43; R >> 1;Add(ls[pa], ls[pb], L, mid); Add(rs[pa], rs[pb], mid &#43; 1, R);
}
void Update(int p, int L, int R, int st, int ed, int c, bool flag) {if(L &#61;&#61; st && ed &#61;&#61; R) {if(flag) add(p, c, 0);else add(c, p, 0);return ;}int mid &#61; L &#43; R >> 1;if(st <&#61; mid) Update(ls[p], L, mid, st, min(mid, ed), c, flag);if(ed > mid) Update(rs[p], mid &#43; 1, R, max(st, mid &#43; 1), ed, c, flag);
}
void Link(int a, int b, int c, int d) {Update(ra, 1, n, a, b, &#43;&#43;sz, 1); add(sz, sz &#43; 1, 1); Update(rb, 1, n, c, d, &#43;&#43;sz, 0);
}void Dij() {for(int i &#61; 1;i <&#61; sz; &#43;&#43;i) dis[i] &#61; inf;priority_queueq;dis[pos[s]] &#61; 0; q.push(data(pos[s], 0));while(!q.empty()) {int u &#61; q.top().a; q.pop();if(vis[u]) continue;vis[u] &#61; true;for(int i &#61; pre[u]; i; i &#61; nxt[i]) if(!vis[to[i]] && dis[to[i]] > dis[u] &#43; w[i]) {dis[to[i]] &#61; dis[u] &#43; w[i];q.push(data(to[i], dis[to[i]]));}}
}int main() {n &#61; read(); m &#61; read(); s &#61; read();Build(ra, 1, n, 1); Build(rb, 1, n, 0); Add(ra, rb, 1, n);for(int i &#61; 1;i <&#61; m; &#43;&#43;i) {int a &#61; read(), b &#61; read(), c &#61; read(), d &#61; read();Link(a, b, c, d); Link(c, d, a, b);}Dij();for(int i &#61; 1;i <&#61; n; &#43;&#43;i) printf("%d\n", dis[pos[i]]);return 0;
}


推荐阅读
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
author-avatar
kingwign0010
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有