1. 程式人生 > >Codeforces-786B-Legacy (線段樹+最短路)

Codeforces-786B-Legacy (線段樹+最短路)

看到區間很容易就能想到線段樹。
對於操作2,我們可以建立一棵線段樹,線段樹的某一個結點表示區間 [l,r] ,那麼在圖中建立一個結點 u 表示區間 [l,r] ,新建點 u 指向 l,l+1,l+2...r 的邊,權值為 0
當得到一個操作 (v,l,r,w) 時,查詢一次線段樹,把所有符合 [ql,qr][l,r] 的極大區間結點建立一條被 v 指向的邊,權值為 w 。這樣就能表示 v 指向 [l,r] 了。
每一次新建邊的操作複雜度是 O(2logn)
對於操作3,與操作2類似。

#include<bits/stdc++.h>
using namespace std
; typedef long long ll; const ll INF=0x3f3f3f3f3f3f3f3f; const int maxn=1e5+7; struct Node { int v; ll d; Node(){} Node(int _v,ll _d):v(_v),d(_d){} bool operator < (const Node & r) const { return d>r.d; } }; int n,q,s; int p_2[maxn<<2],p_3[maxn<<2
]; vector<Node> adj[maxn<<3|1]; bool vis[maxn<<3|1]; ll d[maxn<<3|1]; void build_2(int rt, int l, int r) { p_2[rt]=++n; for(int i=l;i<=r;i++) adj[p_2[rt]].push_back(Node(i,0)); if(l==r) return ; int mid=(l+r)>>1; build_2(rt<<1,l,mid); build_2(rt<<1
|1,mid+1,r); } void build_3(int rt,int l,int r) { p_3[rt]=++n; for(int i=l;i<=r;i++) adj[i].push_back(Node(p_3[rt],0)); if(l==r) return ; int mid=(l+r)>>1; build_3(rt<<1,l,mid); build_3(rt<<1|1,mid+1,r); } void update_2(int rt,int l,int r,int ql,int qr,int id,ll w) { if(l>=ql&&r<=qr) { adj[id].push_back(Node(p_2[rt],w)); return ; } int mid=(l+r)>>1; if(ql<=mid) update_2(rt<<1,l,mid,ql,qr,id,w); if(qr>mid) update_2(rt<<1|1,mid+1,r,ql,qr,id,w); } void update_3(int rt,int l,int r,int ql,int qr,int id,ll w) { if(l>=ql&&r<=qr) { adj[p_3[rt]].push_back(Node(id,w)); return ; } int mid=(l+r)>>1; if(ql<=mid) update_3(rt<<1,l,mid,ql,qr,id,w); if(qr>mid) update_3(rt<<1|1,mid+1,r,ql,qr,id,w); } int main() { scanf("%d%d%d",&n,&q,&s); int on=n; build_2(1,1,on); build_3(1,1,on); int op,l,r,u,v,w; while(q--) { scanf("%d",&op); if(op==1) { scanf("%d%d%d",&v,&u,&w); adj[v].push_back(Node(u,w)); } else { scanf("%d%d%d%d",&v,&l,&r,&w); if(op==2) update_2(1,1,on,l,r,v,w); else update_3(1,1,on,l,r,v,w); } } memset(d,0x3f,sizeof(d)); d[s]=0; priority_queue<Node> q; q.push(Node(s,0)); while(!q.empty()) { Node t=q.top();q.pop(); if(vis[t.v]) continue; vis[t.v]=true; for(int i=0;i<adj[t.v].size();i++) { Node &tt=adj[t.v][i]; if(!vis[tt.v]&&d[t.v]+tt.d<d[tt.v]) { d[tt.v]=d[t.v]+tt.d; q.push(Node(tt.v,d[tt.v])); } } } for(int i=1;i<=on;i++) printf("%I64d ",d[i]==INF?-1:d[i]); return 0; }