日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

模板:线段树优化建图

發(fā)布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 模板:线段树优化建图 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

百川到海,天下歸一

解析

線段樹優(yōu)化建圖是用于對一個區(qū)間的點連邊時的優(yōu)化方法
建一棵in樹一棵出樹分別往上和下指即可
大概長這樣

(pia的洛谷的照片)

建樹

正常動態(tài)開點即可

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);//printf("k=%d l=%d r=%d ls=%d rs=%d\n",k,l,r,tr[k].ls,tr[k].rs);return; }

連邊

和線段樹的通常操作很類似

void add(int k,int l,int r,int x,int y,int o){//printf("add:k=%d l=%d r=%d x=%d y=%d o=%d\n",k,l,r,x,y,o);if(x<=l&&r<=y){//printf(" o=%d k=%d\n",o,k);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ū)間對區(qū)間連邊

不需要對入樹和出樹兩兩相連,只需要新開一個虛點,都對虛點連邊即可
這樣總的加邊數(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){//if(w)//printf("%d %d %d\n",x,y,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){//printf("(%d %d) k=%d ls=%d rs=%d op=%d\n",l,r,k,0,0,op);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);}//printf("(%d %d) k=%d ls=%d rs=%d op=%d\n",l,r,k,ls[k],rs[k],op);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();/*for(int j=a;j<=b;j++){for(int k=c;k<=d;k++){if(j==k) continue;addline(j,k,1);addline(k,j,1);} }*/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);/*find(rout,1,n,a,b,c,d);find(rout,1,n,c,d,a,b);*/}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é)

以上是生活随笔為你收集整理的模板:线段树优化建图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。