• 【BZOJ2459】 [BeiJing2011]神秘好人


    Description

    有一个神秘好人跟Bdcxq玩一个游戏,如果Bdcxq成功完成了这个游戏,那么他将会得到一件礼物。
    这个游戏是这样的:
    有一个梯子形的图如下,每条边都有一个权值。

    神秘好人一开始会告诉Bdcxq每条边的权值。

           然后神秘好人会做这样的事情:

    1.神秘好人会修改某条边的权值;

    2.神秘老人会问你从一个点走到另一个点所需经过边权和最小的权值和。

    如果Bdcxq一直能答对问题,那么他就完成了游戏,也能得到礼物。

    现在他请你编一个程序来帮他完成游戏。

    Input

    输入文件的第一行包含一个整数N,表示梯子总共含有2N个点,第一行从左至右分别标号为13,……,2N-1第二行从左至右分别标号为24,……,2N

    接下来有三行。

    第一行有N-1个整数,依次表示上层相邻两点间的初始权值。

    第二行有N个整数,依次表示两层之间的边的初始权值。

    第三行有N-1个整数,依次表示下层相邻两点间的初始权值。

    接下来一行包含一个整数M,表示神秘好人在游戏开始后的操作。

    接下来M行:

    每行第一个整数若是0,表示这是一个修改操作,接下来会有3个整数Ai,Bi,Ci,Ai为0,1,2分别代表这条边属于上层边,中间边和下层边,Bi表示这条边是这一层从左向右数的第Bi条边,Ci表示要修改成的边权。

    每行第一个整数若是1,表示这是一个询问操作,接下来会有2个整数Ai,Bi,询问Ai到Bi的经过边的最小权值和。

    Output

    对于每次询问操作你需要输出一行包含一个整数,为最小的边权值和。

    Sample Input

    4
    1 2 7
    1 3 4 8
    4 5 6
    5
    1 1 2
    1 2 6
    1 1 8
    0 1 3 1
    1 1 8

    Sample Output

    1
    8
    13
    10

    HINT

    100%的数据满足N,M≤ 100000。

    Solution

    用线段树维护仅在这个区间内走时四个角的最短路的邻接矩阵,然后修改询问就强行维护一波就好啦。这题细节比较多,要注意一下。。。

    Code

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 
      5 #define R register
      6 #define maxn 100010
      7 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
      8 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
      9 typedef long long ll;
     10 struct Data {
     11     ll d[4][4];
     12     inline void init()
     13     {
     14         memset(d, 63, sizeof (d));
     15         for (R int i = 0; i < 4; ++i) d[i][i] = 0;
     16     }
     17     inline void floyd()
     18     {
     19         for (R int k = 0; k < 4; ++k)
     20             for (R int i = 0; i < 4; ++i)
     21                 for (R int j = 0; j < 4; ++j)
     22                     cmin(d[i][j], d[i][k] + d[k][j]);
     23     }
     24     inline Data operator + (const Data &that) const
     25     {
     26         R Data ret; ret.init();
     27         ret.d[0][1] = ret.d[1][0] = dmin(d[0][1], d[0][2] + that.d[0][1] + d[3][1]);
     28         ret.d[2][3] = ret.d[3][2] = dmin(that.d[2][3], that.d[2][0] + d[2][3] + that.d[1][3]);
     29 
     30         ret.d[0][2] = ret.d[2][0] = dmin(d[0][2] + that.d[0][2], d[0][3] + that.d[1][2]);
     31         ret.d[0][3] = ret.d[3][0] = dmin(d[0][2] + that.d[0][3], d[0][3] + that.d[1][3]);
     32         ret.d[1][2] = ret.d[2][1] = dmin(d[1][2] + that.d[0][2], d[1][3] + that.d[1][2]);
     33         ret.d[1][3] = ret.d[3][1] = dmin(d[1][2] + that.d[0][3], d[1][3] + that.d[1][3]);
     34 //        ret.floyd();
     35         return ret;
     36     }
     37 } ;
     38 int u[maxn], m[maxn], d[maxn];
     39 Data tr[maxn << 2];
     40 void update(R int o)
     41 {
     42     tr[o] = tr[o << 1] + tr[o << 1 | 1];
     43 }
     44 void build(R int o, R int l, R int r)
     45 {
     46     if (l == r)
     47     {
     48         tr[o].init();
     49         tr[o].d[0][1] = tr[o].d[1][0] = m[l];
     50         tr[o].d[0][2] = tr[o].d[2][0] = u[l];
     51         tr[o].d[1][3] = tr[o].d[3][1] = d[l];
     52         tr[o].d[2][3] = tr[o].d[3][2] = m[l + 1];
     53         tr[o].floyd();
     54         return ;
     55     }
     56     R int mid = l + r >> 1;
     57     build(o << 1, l, mid);
     58     build(o << 1 | 1, mid + 1, r);
     59     update(o);
     60 }
     61 int ql, qr;
     62 void modify(R int o, R int l, R int r)
     63 {
     64     if (l == r)
     65     {
     66         tr[o].init();
     67         tr[o].d[0][1] = tr[o].d[1][0] = m[l];
     68         tr[o].d[0][2] = tr[o].d[2][0] = u[l];
     69         tr[o].d[1][3] = tr[o].d[3][1] = d[l];
     70         tr[o].d[2][3] = tr[o].d[3][2] = m[l + 1];
     71         tr[o].floyd();
     72         return ;
     73     }
     74     R int mid = l + r >> 1;
     75     if (ql <= mid) modify(o << 1, l, mid);
     76     else modify(o << 1 | 1, mid + 1, r);
     77     update(o);
     78 }
     79 Data query(R int o, R int l, R int r)
     80 {
     81     if (ql <= l && r <= qr) return tr[o];
     82     R Data ret;
     83     R int mid = l + r >> 1;
     84     if (ql <= mid && qr <= mid) return query(o << 1, l, mid);
     85     if (mid < ql && mid < qr) return query(o << 1 | 1, mid + 1, r);
     86     return query(o << 1, l, mid) + query(o << 1 | 1, mid + 1, r);
     87 }
     88 int main()
     89 {
     90     R int n; scanf("%d", &n);
     91     for (R int i = 1; i < n; ++i) scanf("%d", u + i);
     92     for (R int i = 1; i <= n; ++i) scanf("%d", m + i);
     93     for (R int i = 1; i < n; ++i) scanf("%d", d + i);
     94     build(1, 1, n - 1);
     95     R int q; scanf("%d", &q);
     96     for (; q; --q)
     97     {
     98         R int opt, a, b, c; scanf("%d%d%d", &opt, &a, &b);
     99         if (!opt)
    100         {
    101             scanf("%d", &c);
    102             if (a == 0) u[b] = c;
    103             else if (a == 1) m[b] = c;
    104             else d[b] = c;
    105             
    106             if (a != 1 || b != n) ql = b, modify(1, 1, n - 1);
    107             if (a == 1 && b != 1) ql = b - 1, modify(1, 1, n - 1);
    108         }
    109         else
    110         {
    111             R int l = (a + 1) >> 1, lt = (a + 1) & 1, r = (b + 1) >> 1, rt = (b + 1) & 1;
    112             l > r ? std::swap(l, r), std::swap(lt, rt), 1 : 0;
    113             
    114             R Data v1, v2, v3; v1.init(); v2.init(); v3.init();
    115             ql = 1, qr = l - 1;
    116             if (ql <= qr) v1 = query(1, 1, n - 1);
    117             ql = l; qr = r - 1;
    118             if (ql <= qr) v2 = query(1, 1, n - 1);
    119             ql = r; qr = n - 1;
    120             if (ql <= qr) v3 = query(1, 1, n - 1);
    121             
    122             R ll ans = 0;
    123             if (l == r)
    124             {
    125                 ans = dmin(v1.d[2 + lt][2 + rt], v3.d[lt][rt]);
    126             }
    127             else
    128             {
    129 //                for (R int i = 0; i < 4; ++i, puts("")) for (R int j = 0; j < 4; ++j) printf("%d ", v1.d[i][j]);
    130 //                for (R int i = 0; i < 4; ++i, puts("")) for (R int j = 0; j < 4; ++j) printf("%d ", v2.d[i][j]);
    131 //                for (R int i = 0; i < 4; ++i, puts("")) for (R int j = 0; j < 4; ++j) printf("%d ", v3.d[i][j]);
    132                 ans = v2.d[lt][2 + rt];
    133                 cmin(ans, v1.d[2][3] + v2.d[lt ^ 1][2 + rt]);
    134                 cmin(ans, v2.d[lt][2 + (rt ^ 1)] + v3.d[0][1]);
    135                 cmin(ans, v1.d[2][3] + v2.d[lt ^ 1][2 + (rt ^ 1)] + v3.d[0][1]);
    136 /*                cmin(v2.d[0][1], v1.d[2][3]);
    137                 cmin(v2.d[2][3], v3.d[0][1]);
    138                 v2.floyd();
    139                 ans = v2.d[lt][2 + rt];*/
    140             }
    141             printf("%lld
    ", ans);
    142         }
    143     }
    144     return 0;
    145 }
    146 /*
    147 4
    148 1 2 7
    149 1 3 4 8
    150 4 5 6
    151 5
    152 1 1 2
    153 1 2 6
    154 1 1 8
    155 0 1 3 1
    156 1 1 8
    157 */
  • 相关阅读:
    day29
    day28
    day27
    查询区间内有多少个不同的数(线段树/树状数组)
    树状数组变形:带区间修改的树状数组
    特征提取:PCA主成分分析法和NMF非负矩阵分解法
    Trie树
    Logistic&Softmax回归
    高斯贝叶斯分类器(GNB实战)
    朴素贝叶斯分类器(伯努利贝叶斯+高斯贝叶斯+多项式贝叶斯)
  • 原文地址:https://www.cnblogs.com/cocottt/p/7077192.html
Copyright © 2020-2023  润新知