【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 */

 

转载于:https://www.cnblogs.com/cocottt/p/7077192.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值