Http://codeforces.com/contest/787/problem/D
The main topic: There are n points, three kinds have the direction of the edge, these three have to add to the side of a total of M, then the starting point is S, ask, from S to all points of the shortest path is how much?
The first kind of edge: U->v W indicates that the node u to v has a connecting edge with a weighted value of W
Second Edge: U->[l,r] W indicates that the node u to interval [l,r] is connected to a forward edge with a weighted value of W
Third Edge: [L,r]->u w indicates interval [L, r] all nodes to u have a forward edge with a weighted value of W
Ideas:
We know that the Dijstra is optimized with priority_queue, so that the complexity of each node's value access is guaranteed.
Algorithm one:
For the second and third sides respectively, the points of [L,r]->u] are built, then run DIJ. But the worst-case build is O (n*n), so it's definitely going to be tle
As seen from the algorithm one, the bottleneck of this problem is how to deal with the boundary between the interval and the point.
We carefully analyzed the Dijstra later found that each node access times only 1, that is, the priority queue to take out the point, take out after it is impossible to have a smaller than his point, and this point will only visit once.
For the first edge, u->v, then obviously d[v] = D[u] +w, which conforms to the single-point update in the segment tree
For the second edge U->[l,r], then that is, from the U, to the interval [l,r] All the nodes of the Val are modified to D[u] + W, this matches the segment tree in the segment update
For the third kind of edge [l,r]->u
From [L,r]->u path can have countless, then how to make sure D[u] is from the interval [l,r] inside the smallest?
According to Priority_queue, the first point we visited is necessarily the least weighted, so that is to say, assuming that we are currently accessing node x, then x is in the interval [l,r], then x must be the least in the interval [l,r], so we only need to use this d[x] To update, ie d[u] = d[x] + W. Of course, if this [L,r] interval has been used, there is no need to use, pop off, because the subsequent no longer use this range!
So this is a single point update in the line tree.
Que is the maximum value that Priority_queue,tree saves the current node to the right.
Then a value is accessed from the queue, so there is no need to revisit the
//see if it explodes. int! array will not be one dimension less! //You must be careful about the conditions of the winning.#include <bits/stdc++.h>using namespacestd;#pragmaComment (linker, "/stack:102400000,102400000")#defineLL Long Long#defineAll (a) A.begin (), A.end ()#definePB Push_back#defineMk Make_pair#defineFi first#defineSe Second#defineHaha printf ("haha\n")Const intMAXN = 1e5 +5;ConstLL inf =1e16;intN, Q, S;vector<pair<int, Ll> >One[maxn];vector<pair<pair<int,int, Ll> >ER[MAXN], SAN[MAXN];///The tree saves the current node to the right-hand side, que to save the current node's minimum value .intTREE[MAXN <<2];p Air<ll,int> QUE[MAXN <<2]; LL LAZY[MAXN<<2]; LL D[maxn];inlinevoidUpdate_queue (intO, LL val) { if(que[o].fi = = inf +1)return; que[o].fi=min (que[o].fi, Val); if(Lazy[o] = =-1) Lazy[o] =Val; Lazy[o]=min (Lazy[o], Val);}voidPush_down (into) { intLB = o <<1, RB = O <<1|1; if(Lazy[o]! =-1) {update_queue (lb, lazy[o]); Update_queue (RB, Lazy[o]); Lazy[o]= -1; }}/*because for the second case: V->[l,r], the value of [L,r] is the same, so we assume that it is calculated by priority for the third case: [L, R]->v, [l,r] can only be the smallest point to V, because only in this way can guarantee the shortest */voidUpdateintQlintQrintLintRintO, LL val) { //printf ("QL =%d qr =%d L =%d r =%d\n", QL, QR, L, R); if(QL <= l && qr >=R) { if(val = = inf +1) Que[o] =mk (Val, L); ElseUpdate_queue (O, Val); return ; } push_down (o); intMid = (L + r)/2; if(QL <= mid) update (QL, QR, L, Mid, O <<1, Val); if(QR > Mid) Update (QL, QR, mid +1, R, O <<1|1, Val); Que[o]= Min (que[o <<1], Que[o <<1|1]); //printf ("que[%d] =%lld%d val =%lld\n", O, Que[o], Val);}vector<pair<int, Ll> >ve;voidFind_point (intXintLintRinto) { if(L > x | | tree[o] < x)return ; if(L = =R) { while(!san[l].empty () && san[l].back (). fi.fi >=x) {Ve.push_back (Mk (San[l].back () fi.se, San[l].back (). SE)); San[l].pop_back (); } Tree[o]= -1; if(!san[l].empty ()) tree[o] =san[l].back (). fi.fi; return ; } intMid = (L + r)/2; Find_point (X, L, Mid, O<<1); Find_point (x, Mid+1, R, O <<1|1); Tree[o]= Max (Tree[o <<1], Tree[o <<1|1]);}voidsolve () { for(inti =1; I <= N; i++) D[i] =inf; Update (S, S,1N1,0);///Update initial point while(true){ intU = que[1].se; LL Cost= que[1].fi; if(Cost = = inf +1) Break; D[u]=min (cost, d[u]); Update (U, u,1N1, INF +1);///if accessed from the queue, there is no need to access the///First, single point update U->v for(inti =0; I < one[u].size (); i++){ intv = one[u][i].fi; LL W =one[u][i].se; Update (V, V,1N1, D[u] +W); } ///second, paragraph update, u->[l,r] for(inti =0; I < er[u].size (); i++){ intQL = er[u][i].fi.fi, qr = er[u][i].fi.se; LL W =er[u][i].se; Update (QL, QR,1N1, D[u] +W); } ///The third, single-point update, [L, R]->v, where [l,r] contains the U-nodeve.clear (); Find_point (U,1N1); for(inti =0; I < ve.size (); i++){ intv = ve[i].fi; LL W =ve[i].se; Update (V, V,1N1, D[u] +W); } } for(inti =1; I <= N; i++){ if(D[i] = = inf) printf ("-1"); Elseprintf"%lld", D[i]); } cout<<Endl;}voidBuildintLintRinto) { if(L = =R) {Que[o]=MK (INF, L); Tree[o]= -1; if(!san[l].empty ()) tree[o] =san[l].back (). fi.fi; return ; } intMid = (L + r)/2; if(l <= mid) Build (L, Mid, O <<1); if(R > Mid) Build (mid +1, R, O <<1|1); Tree[o]= Max (Tree[o <<1], Tree[o <<1|1]); Que[o]= Min (que[o <<1], Que[o <<1|1]);}intMain () {CIN>> N >> Q >>s; for(inti =1; I <= Q; i++){ intTy scanf"%d", &ty); if(Ty = =1){ intU, v; LL Val; scanf"%d%d%lld", &u, &v, &val); ONE[U].PB (Mk (V, Val)); } Else { intU, l, R; LL Val; scanf"%d%d%d%lld", &u, &l, &r, &val); if(Ty = =2) ER[U].PB (MK (L, R), Val)); ElseSAN[L].PB (Mk (R, u), Val)); } } for(inti =1; I <= N; i++) sort (All (san[i])); memset (lazy,-1,sizeof(lazy)); Build (1N1); Solve (); return 0;}
View Code
Interval---point, point-to-zone, Segment tree optimization map +dijstra codeforces Round #406 (Div. 2) D