【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\n", 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 */

 

posted @ 2017-06-25 17:00  cot  阅读(219)  评论(0编辑  收藏  举报