生活随笔
收集整理的這篇文章主要介紹了
模板:线段树优化建图
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
前言
百川到海,天下歸一
解析
線段樹(shù)優(yōu)化建圖是用于對(duì)一個(gè)區(qū)間的點(diǎn)連邊時(shí)的優(yōu)化方法
建一棵in樹(shù)一棵出樹(shù)分別往上和下指即可
大概長(zhǎng)這樣
(pia的洛谷的照片)
建樹(shù)
正常動(dòng)態(tài)開(kāi)點(diǎn)即可
void build(int &k
,int l
,int r
){tr
[k
=++tot
]=(tree
){0,0};if(l
==r
){addline(k
,l
);return;}build(tr
[k
].ls
,l
,mid
);build(tr
[k
].rs
,mid
+1,r
);addline(k
,tr
[k
].ls
);addline(k
,tr
[k
].rs
);return;
}
連邊
和線段樹(shù)的通常操作很類(lèi)似
void add(int k
,int l
,int r
,int x
,int y
,int o
){if(x
<=l
&&r
<=y
){addline(o
,k
);return;}if(x
<=mid
) add(tr
[k
].ls
,l
,mid
,x
,y
,o
);if(y
>mid
) add(tr
[k
].rs
,mid
+1,r
,x
,y
,o
);return;
}
區(qū)間對(duì)區(qū)間連邊
不需要對(duì)入樹(shù)和出樹(shù)兩兩相連,只需要新開(kāi)一個(gè)虛點(diǎn),都對(duì)虛點(diǎn)連邊即可
這樣總的加邊數(shù)就是單log的
#include<bits/stdc++.h>
using namespace std
;
#define ll long long
const int N
=5e5+100;
const int M
=1e6+100;
ll
read(){ll x
=0,f
=1;char c
=getchar();while(!isdigit(c
)){if(c
=='-')f
=-1;c
=getchar();}while(isdigit(c
)){x
=x
*10+(c
^48);c
=getchar();}return x
*f
;
}inline void Max(int &x
,int y
){if(x
<y
) x
=y
;}int n
;
struct node{int to
,nxt
,w
;
}p
[N
*205];
int fi
[N
<<3],cnt
;
inline void addline(int x
,int y
,int w
){p
[++cnt
]=(node
){y
,fi
[x
],w
};fi
[x
]=cnt
;return;
}
int ls
[N
<<3],rs
[N
<<3],rin
,rout
,tot
;
#define mid ((l+r)>>1)
void build(int &k
,int l
,int r
,int op
){k
=++tot
;if(l
==r
){if(op
==0) addline(k
,l
,0);else addline(l
,k
,0);return;}build(ls
[k
],l
,mid
,op
);build(rs
[k
],mid
+1,r
,op
);if(op
==0){addline(k
,ls
[k
],0);addline(k
,rs
[k
],0);}else{addline(ls
[k
],k
,0);addline(rs
[k
],k
,0);}return;
}
void add(int k
,int l
,int r
,int x
,int y
,int o
,int op
){if(x
<=l
&&r
<=y
){if(op
==0) addline(o
,k
,op
);else addline(k
,o
,op
);return;}if(x
<=mid
) add(ls
[k
],l
,mid
,x
,y
,o
,op
);if(y
>mid
) add(rs
[k
],mid
+1,r
,x
,y
,o
,op
);return;
}
int s
,m
;
int dis
[N
<<3],vis
[N
<<3];
deque
<int>q
;
int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifmemset(fi
,-1,sizeof(fi
));cnt
=-1;n
=read();m
=read();s
=read();tot
=n
;build(rin
,1,n
,0);build(rout
,1,n
,1);for(int i
=1;i
<=m
;i
++){int a
=read(),b
=read(),c
=read(),d
=read();int o
=++tot
;add(rin
,1,n
,a
,b
,o
,0);add(rout
,1,n
,c
,d
,o
,1);o
=++tot
;add(rin
,1,n
,c
,d
,o
,0);add(rout
,1,n
,a
,b
,o
,1);}memset(dis
,0x3f,sizeof(dis
));q
.push_back(s
);dis
[s
]=0;while(!q
.empty()){int now
=q
.front();q
.pop_front();if(vis
[now
]) continue;vis
[now
]=1;for(int i
=fi
[now
];~i
;i
=p
[i
].nxt
){int to
=p
[i
].to
;if(dis
[now
]+p
[i
].w
>=dis
[to
]) continue;dis
[to
]=dis
[now
]+p
[i
].w
;if(p
[i
].w
) q
.push_back(to
);else q
.push_front(to
);}}for(int i
=1;i
<=n
;i
++) printf("%d\n",dis
[i
]);
}
thanks for reading!
總結(jié)
以上是生活随笔為你收集整理的模板:线段树优化建图的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。