[#3073. Pa2011]Journeys (线段树优化连边)

这张图太直观了,直接讲透了线段树优化连边的原理和正确性。

考虑建立两颗线段树,一颗是外向树,一颗是内向树,相当于网络流建模一样,我们可以利用这两颗线段树分别模拟一个点的入度和出度。毕竟一个点如果确定了它的入度和出度就相当于确定了在图中的位置。

外向树

一条边进入了一个父亲节点,相当于能进入它所有的儿子,这就模拟了入度。这和线段树很像,于是我们就做成线段树的样子,每次加边的时候,最多从外向树选出\(O(\log n)​\)的节点,就可以模拟出区间添加入度的操作。为了真正落实可以免费进入儿子的效果,我们每个节点向儿子连一条边权为0的边。

内向树

一条边从一个父亲节点出去,相当于他所有的儿子可以从这条边出去,这就模拟了出度。这和线段树很像,于是我们就做成线段树的样子,每次加边的时候,最多从外向树选出\(O(\log n)\)的节点,就可以模拟出区间添加出度的操作。为了真正落实可以免费从儿子出的效果,我们每个节点向父亲连一条边权为0的边。

两个操作加起来,就成功添加了一条有向边,边数是\(n\log n​\)级别的。

实现方式

每次要加边时,我们如果\(O(\log^2n)\)地加的话,就会导致边数多一个\(\log\),所以我们新建一个点,再添加,就会用\(O(n)\)的点换来\(O(n \log n )\)的边数了。

线段树不一定真的要建出来(我觉得甚至用树状数组或者循环控制都行啊,因为我们主要是要得到一个二叉关系)。原图我们就可以丢了,原图的点就变成了外向树的叶子节点,对于这两颗线段树一起看做一个新图操作就好了。

由于从同一个点到同一个点是不用花费任何代价的,但是我们也不能有自环,所以我们从每个节点的入度节点到出度节点连一条边权为0的边。

代码人丑常数/内存都大,仅供参考。

//@winlere
#include<bits/stdc++.h>
using namespace std; typedef long long ll;
template < class ccf > inline ccf qr(ccf ret){ ret=0;
register char c=getchar();
while(not isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+c-48,c=getchar();
return ret;
}inline int qr(){return qr(1);}
const int maxn=5e5;
int n,m,k,T;
int d[(int)(maxn*4.6)];
const int inf=1<<18;
typedef pair < int , int > P; priority_queue < P , vector < P > , greater < P > > q;
struct E{unsigned long long to:30,w:2,nx:30;E(){to=w=nx=0;}E(const int&a,const int&b,const int&c){to=a;w=b;nx=c;}};
vector < E > e;
vector < int > v1,v2;
int head[(int)(maxn*4.6)];
int cnt;
inline void add(const int&fr,const int&to,const int&w){
e.push_back(E(to,w,head[fr]));head[fr]=e.size()-1;
} #define st first
#define nd second
#define midd register int mid=(l+r)>>1 #define lef l,mid,pos<<1
#define rgt mid+1,r,pos<<1|1
#define push(a,b) push(make_pair(a,b))
void build1(const int&l,const int&r,const int&pos){//外向树
midd;T=max(pos,T);
if(l==r)return;
add(pos,pos<<1,0);add(pos,pos<<1|1,0);
build1(lef);build1(rgt);
} void build2(const int&l,const int&r,const int&pos){//内向树
midd;
if(l==r)return;
add((pos<<1)+T,pos+T,0);add((pos<<1|1)+T,pos+T,0);
build2(lef);build2(rgt);
} void que(vector < int >&ve,const int&L,const int&R,const int&l,const int&r,const int&pos){
if(L>r||R<l)return;midd;
if(L<=l&&r<=R){ve.push_back(pos);return;}
que(ve,L,R,lef);que(ve,L,R,rgt);
} void ans(const int&l,const int&r,const int&pos){
if(l==r){printf("%d\n",d[pos]);return;}
midd;ans(lef);ans(rgt);
} inline void dij(int S){
for(register int t=1;t<=T;++t) d[t]=d[t+T]=inf,add(t,t+T,0);
for(register int t=T<<1|1;t<=cnt;++t) d[t]=inf;
d[S]=0;
q.push(0,S);
add(S+T,S,0);
while(not q.empty()){
register P temp=q.top();q.pop();
for(register int t=head[temp.nd];t;t=e[t].nx)
if(d[e[t].to]>d[temp.nd]+e[t].w)
d[e[t].to]=d[temp.nd]+e[t].w,q.push(d[e[t].to],(int)e[t].to);
}
} inline void add(const vector < int >&fr,const vector < int >&to){
++cnt;
for(register auto f:fr) add(cnt,f,1);
for(register auto f:to) add(f+T,cnt,0);
} int main(){
e.push_back(::E());
n=qr(1);m=qr(1);k=qr(1);
build1(1,n,1),build2(1,n,1);
cnt=T<<1;
for(register int t=1,t1,t2,t3,t4;t<=m;++t){
t1=qr();t2=qr();t3=qr();t4=qr();
que(v1,t1,t2,1,n,1);
que(v2,t3,t4,1,n,1);
add(v1,v2),add(v2,v1);
v1.clear();v2.clear();
}
que(v1,k,k,1,n,1);
dij(*v1.begin());
ans(1,n,1);
return 0;
}

【题解】Journeys(线段树优化连边)的更多相关文章

  1. [bzoj3073] Journeys 题解(线段树优化建图)

    Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建 ...

  2. 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

    题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...

  3. bzoj 3073: [Pa2011]Journeys -- 线段树优化最短路

    3073: [Pa2011]Journeys Time Limit: 20 Sec  Memory Limit: 512 MB Description     Seter建造了一个很大的星球,他准备建 ...

  4. BZOJ3073: [Pa2011]Journeys(线段树优化建图 Dijkstra)

    题意 \(n\)个点的无向图,构造\(m\)次边,求\(p\)到任意点的最短路. 每次给出\(a, b, c, d\) 对于任意\((x_{a \leqslant x \leqslant b}, y_ ...

  5. 【CF115E】Linear Kingdom Races 题解(线段树优化DP)

    前言:前辈讲课时设的状态还是有些繁琐,感觉题解设的状态更简洁. -------------- 题目链接 题目大意:给定$n$条道路和$m$场比赛,每个道路修建需要$c_i$,每场比赛需要使用$[l_i ...

  6. bzoj 3073 [Pa2011]Journeys ——线段树优化连边

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073 建两棵线段树,一棵孩子向父亲连边,是走出去的:一棵父亲向孩子连边,是走进来的. 注意第 ...

  7. bzoj 3073 Journeys —— 线段树优化连边

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073 建两棵线段树,一棵从下往上连边,一棵从上往下连边,叶子节点之间也有连边: 区间向区间连 ...

  8. Codeforces Round #426 (Div. 2) D 线段树优化dp

    D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  9. CF786B Legacy 线段树优化建图 + spfa

    CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...

随机推荐

  1. <转> lua: userdata的metatable使用

    1 如何封装c++的指针 对于c++对象的lua包装,我们可以使用 template<typename T> struct luaUserdataWrapper {  luaUserdat ...

  2. Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.cache.ehcache.EhCacheRegionFactory] as strategy [org.hibernate.cache.spi.RegionFac

    警告: Exception encountered during context initialization - cancelling refresh attempt: org.springfram ...

  3. xml文件的增删改读

    最近学习了利用XmlDocument对象对xml进行增删改读操作,就写了一个小的例子记录下来,加深印象,以后忘了也可以找出来看看. xml文件: <?xml version="1.0& ...

  4. UIAlertViewController 2

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...

  5. CMD常用功能

    1.导出文件目录树状结构 命令:“tree>file.txt /f”

  6. 安装ecshop默认安装后的错误解决方案

    1,统一解决 php.ini中的配置 error_reporting = E_ALL | E_STRICT 这是说,显示那些不符合编码规范的警告(coding standards warnings). ...

  7. es模板

    Index Templatesedit Index templates allow you to define templates that will automatically be applied ...

  8. 请实现一个函数,把字符串中的每一个空格替换成“%20”,比如输入 “We are Happly。” 则输出“we%20are%20happy。”

    请实现一个函数,把字符串中的每一个空格替换成"%20",比如输入 "We are Happly."  则输出"we%20are%20happy. &q ...

  9. 李洪强经典面试题53-Swift

    李洪强经典面试题53-Swift Swift 网上有很多Swift的语法题,但是Swift现在语法还未稳定,所以在这里暂时不贴出语法题,可以自行搜索. Swift和Objective-C的联系 Swi ...

  10. Java序列化的几种方式

    本文着重解说一下Java序列化的相关内容. 假设对Java序列化感兴趣的同学能够研究一下. 一.Java序列化的作用    有的时候我们想要把一个Java对象变成字节流的形式传出去,有的时候我们想要从 ...