習題:Legacy(線段樹優化建圖)
阿新 • • 發佈:2020-08-24
題目
思路
類似於建虛點
注意到題目中的操作區間都是連續的,用線段樹來優化建圖即可
程式碼
#include<iostream> #include<cstring> #include<vector> #include<queue> using namespace std; struct node_tre { int l; int r; }tre[2][400005];//0表示出,1表示入 struct node_g { int e; long long w; friend bool operator < (const node_g &a,const node_g &b) { return a.w>b.w; } }; int n,m,s; int opt; int u,l,r,w; bool vis[900015]; long long dis[900005]; vector<node_g> g[900015]; priority_queue<node_g> q; void build(int l,int r,int k) { tre[0][k].l=tre[1][k].l=l; tre[0][k].r=tre[1][k].r=r; if(l==r) { g[l].push_back((node_g){n+k,0}); g[5*n+k].push_back((node_g){l,0}); return; } g[n+(k<<1)].push_back((node_g){n+k,0}); g[n+(k<<1|1)].push_back((node_g){n+k,0}); g[5*n+k].push_back((node_g){5*n+(k<<1),0}); g[5*n+k].push_back((node_g){5*n+(k<<1|1),0}); int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); } void change(int l,int r,int st,long long w,int opt,int k) { if(l>tre[opt][k].r||tre[opt][k].l>r) return; if(l<=tre[opt][k].l&&tre[opt][k].r<=r) { if(opt==0) g[st].push_back((node_g){5*n+k,w}); else g[n+k].push_back((node_g){st,w}); return; } change(l,r,st,w,opt,k<<1); change(l,r,st,w,opt,k<<1|1); } void dij(int s) { memset(dis,0x3f,sizeof(dis)); q.push((node_g){s,0}); dis[s]=0; while(!q.empty()) { node_g u=q.top(); q.pop(); if(vis[u.e]) continue; vis[u.e]=1; for(int i=0;i<g[u.e].size();i++) { int v=g[u.e][i].e; long long w=g[u.e][i].w; if(w+dis[u.e]<dis[v]) { dis[v]=w+dis[u.e]; q.push((node_g){v,dis[v]}); } } } } int main() { ios::sync_with_stdio(false); cin>>n>>m>>s; build(1,n,1); for(int i=1;i<=m;i++) { cin>>opt; if(opt==1) { cin>>l>>r>>w; if(l==r) continue; g[l].push_back((node_g){r,w}); } else { opt-=2; cin>>u>>l>>r>>w; change(l,r,u,w,opt,1); } } dij(s); for(int i=1;i<=n;i++) { if(dis[i]==dis[0]) cout<<"-1\n"; else cout<<dis[i]<<'\n'; } return 0; }