Interval---point, point-to-zone, Segment tree optimization map +dijstra codeforces Round #406 (Div. 2) D

Source: Internet
Author: User

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.