3995: [SDOI2015]道路修建
来源:互联网 发布:淘宝店铺进货虚拟 编辑:程序博客网 时间:2024/05/22 01:54
3995: [SDOI2015]道路修建
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 271 Solved: 142
[Submit][Status][Discuss]
Description
某国有2N个城市,这2N个城市构成了一个2行N列的方格网。现在该国政府有一个旅游发展计划,这个计划需要选定L、R两列(L<=R),修建若干条专用道路,使得这两列之间(包括这两列)的所有2(R-L+1)个城市中每个城市可以只通过专用道路就可以到达这2(R-L+1)个城市中的任何一个城市。这种专用道路只能在同一行相邻两列的城市或者同一列的两个城市之间修建,且修建需要花费一定的费用。由于该国政府决定尽量缩减开支,因此政府决定,选定L、R后,只修建2(R-L+1)-1条专用道路,使得这些专用道路构成一个树结构。现在你需要帮助该国政府写一个程序,完成这个任务。具体地,该任务包含M个操作,每个操作的格式如下:
1. C x0 y0 x1 y1 w:由于重新对第x0行第y0列的城市和第x1行第y1列的城市之间的情况进行了考察,它们之间修建一条专用道路的花费变成了w;
2. Q L R:若政府选定的两列分别为L、R,询问政府的最小开支。
Input
第一行,两个整数N、M。
第二行,N-1个整数,其中第i个整数表示初始时第1行第i列的城市和第1行第i+1列的城市之间修建一条专用道路的费用。
第三行,N-1个整数,其中第i个整数表示初始时第2行第i列的城市和第2行第i+1列的城市之间修建一条专用道路的费用。
第四行,N个整数,其中第i个整数表示初始时第1行第i列的城市和第2行第i列的城市之间修建一条专用道路的费用。
接下来的M行,每行一个操作。
Output
对于每个询问操作,输出一行,表示你计算出的政府的最小开支。
Sample Input
3 3
1 2
2 1
3 1 2
Q 1 3
C 1 2 2 2 3
Q 2 3
1 2
2 1
3 1 2
Q 1 3
C 1 2 2 2 3
Q 2 3
Sample Output
7
5
5
HINT
对于全部的数据,1<=N, M<=60000,任何时刻任何一条专用道路的修建费用不超过10^4。
Source
Round 1 感谢yts1999上传
做这题之前建议先做bzoj1018,(大概算是弱化版?),反正思路要从那题借鉴
考虑通过线段树维护保持某个区间某种连通性的最小代价
说是某种,就是分类讨论这个区间内四个角构成不同形态连通块的情形
大致可以简易分成以下五大类
这样,一次询问对应到线段树上O(logn)个区间
把这些节点拿出来,讨论合并一下就行了
#include<iostream>#include<cstdio>#include<cstring>using namespace std; const int maxn = 6E4 + 60;const int T = 4;const int INF = 1E9 + 233; struct Node{ int a[5]; Node(){for (int i = 0; i < 5; i++) a[i] = INF;}}c[maxn*T],stk[maxn],Ans;int n,m,tp,E[2][maxn][3],Left[maxn]; Node Merge(Node L,Node R,int S,int M){ Node ret; ret.a[0] = min(ret.a[0],L.a[0] + R.a[0] + M); ret.a[0] = min(ret.a[0],L.a[0] + R.a[1] + S); ret.a[2] = min(ret.a[2],L.a[0] + R.a[2] + M); ret.a[0] = min(ret.a[0],L.a[0] + R.a[3] + S); ret.a[2] = min(ret.a[2],L.a[0] + R.a[3] + M); ret.a[2] = min(ret.a[2],L.a[0] + R.a[4] + S); ret.a[1] = min(ret.a[1],L.a[1] + R.a[0] + M); ret.a[1] = min(ret.a[1],L.a[1] + R.a[1] + S); ret.a[4] = min(ret.a[4],L.a[1] + R.a[2] + M); ret.a[1] = min(ret.a[1],L.a[1] + R.a[3] + S); ret.a[4] = min(ret.a[4],L.a[1] + R.a[3] + M); ret.a[4] = min(ret.a[4],L.a[1] + R.a[4] + S); ret.a[0] = min(ret.a[0],L.a[2] + R.a[0] + S); ret.a[2] = min(ret.a[2],L.a[2] + R.a[2] + S); ret.a[2] = min(ret.a[2],L.a[2] + R.a[3] + S); ret.a[0] = min(ret.a[0],L.a[3] + R.a[0] + S); ret.a[1] = min(ret.a[1],L.a[3] + R.a[0] + M); ret.a[1] = min(ret.a[1],L.a[3] + R.a[1] + S); ret.a[4] = min(ret.a[4],L.a[3] + R.a[2] + M); ret.a[2] = min(ret.a[2],L.a[3] + R.a[2] + S); ret.a[4] = min(ret.a[4],L.a[3] + R.a[3] + M); ret.a[3] = min(ret.a[3],L.a[3] + R.a[3] + S); ret.a[4] = min(ret.a[4],L.a[3] + R.a[4] + S); ret.a[1] = min(ret.a[1],L.a[4] + R.a[0] + S); ret.a[4] = min(ret.a[4],L.a[4] + R.a[2] + S); ret.a[4] = min(ret.a[4],L.a[4] + R.a[3] + S); return ret;} void Build(int o,int l,int r){ if (l == r) { c[o].a[0] = E[0][l][2]; c[o].a[3] = 0; return; } int mid = l + r >> 1,U,D; Build(o<<1,l,mid); Build(o<<1|1,mid+1,r); U = E[0][mid][1],D = E[1][mid][1]; c[o] = Merge(c[o<<1],c[o<<1|1],U + D,min(U,D));} void Modify(int o,int l,int r,int ql,int qr){ if (l == r) {c[o].a[0] = E[0][l][2]; return;} int mid = l + r >> 1,U,D; if (ql <= mid) Modify(o<<1,l,mid,ql,qr); if (qr > mid) Modify(o<<1|1,mid+1,r,ql,qr); U = E[0][mid][1],D = E[1][mid][1]; c[o] = Merge(c[o<<1],c[o<<1|1],U + D,min(U,D));} void GetRange(int o,int l,int r,int ql,int qr){ if (ql <= l && r <= qr) { stk[++tp] = c[o]; Left[tp] = l; return; } int mid = l + r >> 1; if (ql <= mid) GetRange(o<<1,l,mid,ql,qr); if (qr > mid) GetRange(o<<1|1,mid+1,r,ql,qr);} int getint(){ char ch = getchar(); int ret = 0; while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') ret = ret * 10 + ch - '0',ch = getchar(); return ret;} int getcom(){ char ch = getchar(); while (ch != 'C' && ch != 'Q') ch = getchar(); return ch == 'C' ? 1 : 2;} int main(){ #ifdef DMC freopen("DMC.txt","r",stdin); #endif n = getint(); m = getint(); for (int i = 1; i < n; i++) E[0][i][1] = E[0][i + 1][0] = getint(); for (int i = 1; i < n; i++) E[1][i][1] = E[1][i + 1][0] = getint(); for (int i = 1; i <= n; i++) E[0][i][2] = E[1][i][2] = getint(); Build(1,1,n); while (m--) { int com = getcom(); if (com == 1) { int r1,c1,r2,c2,w; r1 = getint(); c1 = getint(); r2 = getint(); c2 = getint(); --r1; --r2; w = getint(); if (c1 != c2) { if (c1 > c2) swap(c1,c2); E[r1][c1][1] = E[r2][c2][0] = w; } else E[r1][c1][2] = E[r2][c2][2] = w; Modify(1,1,n,c1,c2); } else { int l = getint(),r = getint(); tp = 0; GetRange(1,1,n,l,r); Ans = stk[1]; for (int i = 2; i <= tp; i++) { int U = E[0][Left[i]][0],D = E[1][Left[i]][0]; Ans = Merge(Ans,stk[i],U + D,min(U,D)); } printf("%d\n",Ans.a[0]); } } return 0;}
0 0
- 3995: [SDOI2015]道路修建
- BZOJ 3995 SDOI2015 道路修建
- BZOJ 3995: [SDOI2015]道路修建
- BZOJ 3995 [SDOI2015]道路修建
- BZOJ 3995 Sdoi2015 道路修建 线段树
- 【BZOJ3995】【SDOI2015】道路修建
- 道路修建
- 道路修建
- 【NOI2011】道路修建
- 2435: [Noi2011]道路修建
- bzoj2435: [Noi2011]道路修建
- NOI2011道路修建 TreeDp
- [BZOJ2435] [Noi2011]道路修建
- bzoj 2435 道路修建
- [BZOJ2435][Noi2011]道路修建
- GDFZOJ 道路修建
- 【bzoj2435】道路修建
- 【DP】【LIS】道路修建
- PCA 原理
- [华为OJ--C++]046-成绩排序
- Java程序莫名其妙卡死的一次经历
- sed基础使用
- MySQL 的一些坑
- 3995: [SDOI2015]道路修建
- Android 蓝牙开发基本流程
- 理解EnterCriticalSection 临界区
- 机器学习的几大算法。
- select2 4.0.3 空记录时的处理
- 3ds Max .NET二次开发的基础入门篇
- CTF之你能否抓到包?
- 课后练习 1.2
- Ajax使用JSON格式