【BZOJ2459】 [BeiJing2011]神秘好人
Description
有一个神秘好人跟Bdcxq玩一个游戏,如果Bdcxq成功完成了这个游戏,那么他将会得到一件礼物。
这个游戏是这样的:
有一个梯子形的图如下,每条边都有一个权值。
神秘好人一开始会告诉Bdcxq每条边的权值。
然后神秘好人会做这样的事情:
1.神秘好人会修改某条边的权值;
2.神秘老人会问你从一个点走到另一个点所需经过边权和最小的权值和。
如果Bdcxq一直能答对问题,那么他就完成了游戏,也能得到礼物。
现在他请你编一个程序来帮他完成游戏。
Input
输入文件的第一行包含一个整数N,表示梯子总共含有2N个点,第一行从左至右分别标号为1,3,……,2N-1,第二行从左至右分别标号为2,4,……,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
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
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 */