zoukankan      html  css  js  c++  java
  • (难)Codeforces Round #406 (Div. 2) D题Legacy(线段树+最短路)解题报告

    D. Legacy
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.

    There are n planets in their universe numbered from 1 to n. Rick is in planet number s (the earth) and he doesn't know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he's still using its free trial.

    By default he can not open any portal by this gun. There are q plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.

    Plans on the website have three types:

    1. With a plan of this type you can open a portal from planet v to planet u.
    2. With a plan of this type you can open a portal from planet v to any planet with index in range [l, r].
    3. With a plan of this type you can open a portal from any planet with index in range [l, r] to planet v.

    Rick doesn't known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.

    Input

    The first line of input contains three integers nq and s (1 ≤ n, q ≤ 1051 ≤ s ≤ n) — number of planets, number of plans and index of earth respectively.

    The next q lines contain the plans. Each line starts with a number t, type of that plan (1 ≤ t ≤ 3). If t = 1 then it is followed by three integers vu and w where w is the cost of that plan (1 ≤ v, u ≤ n1 ≤ w ≤ 109). Otherwise it is followed by four integers vlr and w where w is the cost of that plan (1 ≤ v ≤ n1 ≤ l ≤ r ≤ n1 ≤ w ≤ 109).

    Output

    In the first and only line of output print n integers separated by spaces. i-th of them should be minimum money to get from earth to i-th planet, or  - 1 if it's impossible to get to that planet.

    Examples
    input
    3 5 1
    2 3 2 3 17
    2 3 2 2 16
    2 2 2 3 3
    3 3 1 1 12
    1 3 3 17
    output
    0 28 12 
    input
    4 3 1
    3 4 1 3 12
    2 2 3 4 10
    1 2 4 16
    output
    0 -1 -1 12 
    Note

    In the first sample testcase, Rick can purchase 4th plan once and then 2nd plan in order to get to get to planet number 2.

    深受启发的一道题,线段树维护的过程中即可完成dijkstra算法中priority_queue的任务,可以很大程度上提高效率。(此代码在Div2的提交中效率暂排第一)

    具体每一步的解释都写在了代码中。

      1 #include<cstdio>
      2 #include <iostream>
      3 #include <vector>
      4 #include <algorithm>
      5 typedef long long ll;
      6 typedef unsigned long long ull;
      7 #define pii pair <int, int>
      8 #define pll pair <ll, ll>
      9 #define mp make_pair
     10 using namespace std;
     11 const int MAX=1e5+5;
     12 const ll INF=(ll)1e18;//dij中初始化使用的INF值
     13 int n,q,s;
     14 vector <pii>yi[MAX];//储存第一种
     15 vector <pair<pii,int> >er[MAX],san[MAX];//储存第二种、第三种
     16 vector <pii>now;
     17 int opt;
     18 int v,u,l,r,w;//对应记录时的各个值
     19 ll d[MAX];//最短路中的d数组
     20 ll lazy[MAX<<2];//懒惰标记
     21 pair<ll,int> que[MAX<<2];//dijkstra中的优先队列,这里采用线段树就不再需要通过priority_queue维护,直接线段树维护即可
     22 int tree[MAX<<2];
     23 /*
     24 对编号为k的点进行“赋”x
     25 */
     26 void sets(int k,ll x)
     27 {
     28     if(que[k].first==INF+1)
     29         return;
     30     que[k].first=min(que[k].first,x);//更新值
     31     if(lazy[k]==-1)
     32         lazy[k]=x;
     33     else
     34         lazy[k]=min(x,lazy[k]);
     35 }
     36 /*
     37 将懒惰值下传
     38 */
     39 void pushdown(int k)
     40 {
     41     if(lazy[k]!=-1)
     42     {
     43         sets(2*k,lazy[k]);
     44         sets(2*k+1,lazy[k]);
     45         lazy[k]=-1;
     46     }
     47 }
     48 /*
     49 将tree范围刷新
     50 */
     51 void re(int k,int l,int r,int x)
     52 {
     53     if(l>x||tree[k]<x)
     54         return;
     55     if(l==r)
     56     {
     57         while(!san[l].empty()&&san[l].back().first.first>=x)
     58         {
     59             now.push_back(mp(san[l].back().first.second,san[l].back().second));
     60             san[l].pop_back();
     61         }
     62         if(san[l].empty())
     63             tree[k]=-1;
     64         else
     65             tree[k]=san[l].back().first.first;
     66         return;
     67     }
     68     int mid=l+r>>1;
     69     re(2*k,l,mid,x);re(2*k+1,mid+1,r,x);
     70     tree[k]=max(tree[2*k],tree[2*k+1]);
     71 }
     72 /*
     73 更新函数.将[ul,ur]“更新”为x
     74 */
     75 void update(int ul,int ur,int l,int r,int k,ll x)
     76 {
     77     if(ul==l&&ur==r)
     78     {
     79         sets(k,x);return;
     80     }
     81     else
     82     {
     83         pushdown(k);
     84         int mid=l+r>>1;
     85         if(ur<=mid)
     86             update(ul,ur,l,mid,2*k,x);
     87         else if(ul>mid)
     88             update(ul,ur,mid+1,r,2*k+1,x);
     89         else
     90         {
     91             update(ul,mid,l,mid,2*k,x);update(mid+1,ur,mid+1,r,2*k+1,x);
     92         }
     93         que[k]=min(que[2*k],que[2*k+1]);
     94     }
     95 }
     96 //void upd(int k,int l,int r,int x)
     97 //{
     98 //    if(l==r)
     99 //
    100 //}
    101 /*
    102 "终止“函数,将指定位置赋值为INF+1,使其在接下来的操作不再进行
    103 */
    104 void stop(int l,int r,int k,int lo)
    105 {
    106     if(l==r)
    107         que[k]=mp(INF+1,l);
    108     else
    109     {
    110         pushdown(k);
    111         int mid=l+r>>1;
    112         if(lo<=mid)
    113             stop(l,mid,2*k,lo);
    114         else
    115             stop(mid+1,r,2*k+1,lo);
    116         que[k]=min(que[2*k],que[2*k+1]);
    117     }
    118 
    119 }
    120 /*
    121 初始建树,只考虑第三种情况的区间大小
    122 tree维护区间内每点为第三种情况起点时所有对应区间右侧的最大值的最大值
    123 */
    124 void build(int k,int l,int r)
    125 {
    126     lazy[k]=-1;
    127     if(l==r)
    128     {
    129         que[k]=mp(INF,l);
    130         if(!san[l].empty())//如果存在以此点为起点的第三种情况区间
    131         {
    132             tree[k]=san[l].back().first.first;//之前已经排好序,取最长的右端作为此叶子结点值即可
    133         }
    134         else
    135             tree[k]=-1;//不然不存在这样的区间,赋值为-1
    136         return;
    137     }
    138         int mid=l+r>>1;
    139         build(2*k,l,mid);
    140         build(2*k+1,mid+1,r);
    141         tree[k]=max(tree[2*k],tree[2*k+1]);
    142         que[k]=min(que[2*k],que[2*k+1]);
    143 }
    144 
    145 void dijkstra(int s)//从s点开始进行dij算法求最短路
    146 {
    147     fill(d+1,d+n+1,INF);
    148     update(s,s,1,n,1,0);
    149     while(1)
    150     {
    151         int v=que[1].second;
    152         ll zhi=que[1].first;
    153         if(zhi==INF+1)
    154             break;
    155         d[v]=zhi;
    156         stop(1,n,1,v);
    157         for(int i=0;i<(int)yi[v].size();i++)
    158         {
    159             int u=yi[v][i].first,w=yi[v][i].second;
    160             update(u,u,1,n,1,d[v]+w);//dij中的操作
    161         }
    162         for(int i=0;i<(int)er[v].size();i++)
    163         {
    164             int l=er[v][i].first.first,r=er[v][i].first.second,w=er[v][i].second;
    165             update(l,r,1,n,1,d[v]+w);
    166         }
    167         now.clear();
    168         re(1,1,n,v);
    169         for(int i=0;i<(int)now.size();i++)
    170         {
    171             int u = now[i].first;
    172             int w = now[i].second;
    173             update(u,u,1,n,1,w+d[v]);
    174         }
    175     }
    176 }
    177 int main()
    178 {
    179     scanf("%d%d%d",&n,&q,&s);
    180     while(q--)
    181     {
    182         scanf("%d",&opt);
    183         if(opt==1)
    184         {
    185             scanf("%d%d%d",&v,&u,&w);
    186             yi[v].push_back(mp(u,w));
    187         }
    188         else
    189         {
    190             scanf("%d%d%d%d",&v,&l,&r,&w);
    191             if(opt==2)
    192                 er[v].push_back(mp(mp(l,r),w));
    193             else
    194                 san[l].push_back(mp(mp(r,v),w));
    195         }
    196     }
    197     for(int i=1;i<=n;i++)
    198         sort(san[i].begin(),san[i].end());
    199     build(1,1,n);
    200     dijkstra(s);
    201     for (int i = 1; i <= n; i++) {
    202         if (d[i] == INF) {
    203             printf("-1 ");
    204         } else
    205         {
    206             printf("%I64d ",d[i]);
    207         }
    208     }
    209     return 0;
    210 }
    D. Legacy
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.

    There are n planets in their universe numbered from 1 to n. Rick is in planet number s (the earth) and he doesn't know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he's still using its free trial.

    By default he can not open any portal by this gun. There are q plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.

    Plans on the website have three types:

    1. With a plan of this type you can open a portal from planet v to planet u.
    2. With a plan of this type you can open a portal from planet v to any planet with index in range [l, r].
    3. With a plan of this type you can open a portal from any planet with index in range [l, r] to planet v.

    Rick doesn't known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.

    Input

    The first line of input contains three integers nq and s (1 ≤ n, q ≤ 1051 ≤ s ≤ n) — number of planets, number of plans and index of earth respectively.

    The next q lines contain the plans. Each line starts with a number t, type of that plan (1 ≤ t ≤ 3). If t = 1 then it is followed by three integers vu and w where w is the cost of that plan (1 ≤ v, u ≤ n1 ≤ w ≤ 109). Otherwise it is followed by four integers vlr and w where w is the cost of that plan (1 ≤ v ≤ n1 ≤ l ≤ r ≤ n1 ≤ w ≤ 109).

    Output

    In the first and only line of output print n integers separated by spaces. i-th of them should be minimum money to get from earth to i-th planet, or  - 1 if it's impossible to get to that planet.

    Examples
    input
    3 5 1
    2 3 2 3 17
    2 3 2 2 16
    2 2 2 3 3
    3 3 1 1 12
    1 3 3 17
    output
    0 28 12 
    input
    4 3 1
    3 4 1 3 12
    2 2 3 4 10
    1 2 4 16
    output
    0 -1 -1 12 
    Note

    In the first sample testcase, Rick can purchase 4th plan once and then 2nd plan in order to get to get to planet number 2.

  • 相关阅读:
    2020软件工程作业04(2.0)
    2020软件工程作业03
    软件工程作业02
    2020软件工程作业02
    2020软件工程作业01
    2020软件工程个人作业06——软件工程实践总结作业
    2020软件工程作业05
    2020软件工程作业00——问题清单
    2020软件工程作业04
    2020软件工程作业02
  • 原文地址:https://www.cnblogs.com/quintessence/p/6618559.html
Copyright © 2011-2022 走看看