[#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. jQuery框架源码解读

    1.jQuery 1.9.1 parseJSON: function( data ) { // Attempt to parse using the native JSON parser first ...

  2. shell脚本与mongo交互

    1.mongo提供*.js的方法供linux调用 #!/bin/bash /usr/local/mongodb/bin/mongo hostname/dbname xxx.js xxx.js 内容如下 ...

  3. Android Volley框架的几种post提交请求方式

    首先简单描述一下Google的Android开发团队在2013年推出的一个网络通信框架Volley.它的设计目标是进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如下载文件等,Vol ...

  4. mysql 应用场景

    一.按时间点来统计 ), date_FORMAT(date_Field,'%Y-%m-%d %H:00:00') as dateStr from table_name group by dateStr

  5. Atitit .c#的未来新特性计划草案

    Atitit .c#的未来新特性计划草案 1. C#的未来:追踪空引用1 1.1. 2. 变量命名空间1 1.2. 10. 项目引用Native dll2 1.3. 10. 项目引用Native dl ...

  6. DatabaseFactory.CreateDatabase 方法操作数据库

    using Microsoft.Practices.EnterpriseLibrary.Data;using Microsoft.Practices.EnterpriseLibrary.Data.Sq ...

  7. PHP修改memory_limit的三种办法

     PHP修改memory_limit的三种办法 2010-06-11 10:57:11 分类: 可能是分词程序的问题.只要搜索的字段达到十个汉字以上,就会出现诸如以下的错误 Fatal error: ...

  8. java - day10 - TetrominoTesting

    图形试验,主要 向上造型 package com.example; /** * Created by Administrator on 17-5-23. */ public class Tetromi ...

  9. mysql之replicate_do_table/replicate_ingore_table/replicate_wide_do_table/replicate_wide_ingore_table

    参考:http://yhqlzz.blog.51cto.com/2557314/1159084/ mysql官网:http://dev.mysql.com/doc/refman/5.1/en/repl ...

  10. 关于WPF界面框架MahApps.Metro的一个BUG

    碰到了这个问题,记录一下,以便以后查阅: 在一个WPF项目中使用MahApps.Metro界面框架,其中有一个功能是嵌入一个带句柄的标记. 首先WPF是出了窗体和WebBrowser带有句柄外,其他控 ...