[bzoj3995] [SDOI2015]道路修建 线段树
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
Sample Output
7
5
HINT
对于全部的数据,1<=N, M<=60000,任何时刻任何一条专用道路的修建费用不超过10^4。
Source
Solution
这题就是一个\(2*n\)的网格图,求区间最小生成树,支持单边修改。
我会kruskal!然而并没有什么用
考虑这样的图的最小生成树长什么样,以及是否存在可合并性。
显而易见的是一定至少有一条竖边。
再接着分析,如果要合并两个相邻但不连通的最小生成树,我们有一个非常好的办法:
先连接上下两条边,这时候一定能够形成一个矩形形状的环,我们在这个环中找到最大的元素,并且删去,这样就完成了相邻的最小生成树的合并。
所以我们用线段树的话,每个节点需要维护的信息如下:
左右端点,最左最右竖边的权值,以及最左最右竖边向左(右)延伸到尽头的边最大值(类似一个三面半包围结构),所有横边的最大值,答案,竖边的个数。
合并的时候,左右端点,所有横边的最大值,答案,竖边个数可以直接求出。但是有需要特判的地方:
如果某一边的竖边只有一个,那么新的左右竖边权值,左右竖边左右延伸最大值都要根据情况去变化。
千万要写else!!不然两边权值相等并且两边各只有一个竖边的话会发生奇怪的错误。
其实代码并不难写只是细节有点多
Code
#include <bits/stdc++.h>
using namespace std;
#define N 60005
#define mid ((l+r)>>1)
int a,b,c,d,e,n,m,v[N][3];char o[5];
struct nod{int l,r,lm,rm,ls,rs,am,ans,cnt;void init(int x){lm=rm=ls=rs=ans=v[x][2];cnt=1;am=0;}}s[N*4];
nod merge(nod x,nod y)
{
nod z;z.l=x.l;z.r=y.r;
int mxh=max(v[x.r][0],v[x.r][1]),mx=max(max(x.rm,y.lm),mxh);
z.ans=x.ans+y.ans+v[x.r][0]+v[x.r][1]-mx;z.am=max(max(x.am,y.am),mxh);z.cnt=x.cnt+y.cnt;
if(mx==x.rs&&x.cnt==1) z.lm=max(x.am,max(y.lm,mxh)),z.rm=y.rm,z.ls=y.ls,z.rs=y.rs,z.cnt--;
else if(mx==y.ls&&y.cnt==1) z.lm=x.lm,z.rm=max(y.am,max(mxh,x.rm)),z.ls=x.ls,z.rs=x.rs,z.cnt--;
else z.lm=x.lm,z.rm=y.rm,z.ls=x.ls,z.rs=y.rs,z.cnt-=(mx==x.rs||mx==y.ls);
return z;
}
void bud(int x,int l,int r)
{
if(l==r){s[x].init(l);s[x].l=l;s[x].r=r;return;}
bud(x*2,l,mid);bud(x*2+1,mid+1,r);s[x]=merge(s[x*2],s[x*2+1]);
}
void upd(int x,int l,int r,int p)
{
if(l==r){s[x].init(l);return;}
if(p<=mid) upd(x*2,l,mid,p);else upd(x*2+1,mid+1,r,p);s[x]=merge(s[x*2],s[x*2+1]);
}
nod que(int x,int l,int r,int b,int e)
{
if(b<=l&&r<=e) return s[x];
if(e<=mid) return que(x*2,l,mid,b,e);if(b>mid) return que(x*2+1,mid+1,r,b,e);
return merge(que(x*2,l,mid,b,e),que(x*2+1,mid+1,r,b,e));
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++) scanf("%d",&v[i][0]);
for(int i=1;i<n;i++) scanf("%d",&v[i][1]);
for(int i=1;i<=n;i++) scanf("%d",&v[i][2]);
bud(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%s",o);
if(o[0]=='Q') scanf("%d%d",&a,&b),printf("%d\n",que(1,1,n,a,b).ans);
else
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);if(b>d) swap(b,d);
if(a!=c) v[b][2]=e,upd(1,1,n,b);else v[b][a-1]=e,upd(1,1,n,b);
}
}
}
[bzoj3995] [SDOI2015]道路修建 线段树的更多相关文章
- 【BZOJ3995】[SDOI2015]道路修建 线段树区间合并
[BZOJ3995][SDOI2015]道路修建 Description 某国有2N个城市,这2N个城市构成了一个2行N列的方格网.现在该国政府有一个旅游发展计划,这个计划需要选定L.R两列(L&l ...
- [SDOI2015]道路修建(线段树)
题意:给定2行n列的四连通带权网格图,支持修改边权和查询第[l,r]列的最小生成树 题解:这是一道好题,要么SDOI2019中n=2的20pts怎么会“我抄我自己”?(当然NOIP2018“我抄我自己 ...
- 【线段树】bzoj3995 [SDOI2015]道路修建
线段树每个结点维护5个域: 整个区间的MST. 将两个左端点连通,两个右端点不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块. 将两个右端点连通,两个左端点不连通,整个区间 ...
- bzoj3995[SDOI2015]道路修建
http://www.lydsy.com/JudgeOnline/problem.php?id=3995 线段树维护连通性. 我们发现,对于一个区间[L,R],我们只需要知道(1,L),(2,L),( ...
- [BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】
题目链接:BZOJ - 3995 题目分析 这道题..是我悲伤的回忆.. 线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过 1018,即使它在 ProblemSet 的第一页 ...
- 洛谷P2505||bzoj2750 [HAOI2012]道路 && zkw线段树
https://www.luogu.org/problemnew/show/P2505 https://www.lydsy.com/JudgeOnline/problem.php?id=2750 神奇 ...
- LOJ #2831. 「JOISC 2018 Day 1」道路建设 线段树+Link-cut-tree
用 LCT 维护颜色相同连通块,然后在线段树上查一下逆序对个数就可以了. code: #include <cstdio> #include <algorithm> #inclu ...
- BZOJ 2435:[Noi2011]道路修建(树型DP)
http://www.lydsy.com/JudgeOnline/problem.php?id=2435 题意:中文题意. 思路:很简单的树形DP,sz记录儿子有多少个和cur记录走的哪条弧,然后直接 ...
- 【XSY2528】道路建设 LCT 可持久化线段树
题目描述 给你一个\(n\)个点\(m\)条边图,\(q\)个询问,每次问你边权在\([l,r]\)之间的边组成的最小生成树(森林)的边权和.强制在线. \(n,m,q\leq 100000\) 题解 ...
随机推荐
- 使用opencv3+python实现视频运动目标检测
本文主要实现了伯乐在线上的一个实践小项目,原文链接,用以巩固opencv视频操作知识内容.整个项目均有代码注释,通俗易懂,短短几十行就可以达到还算不错的实现效果,做起来成就感满满哒.打开编辑器,一起来 ...
- CHEMISTS DISCOVER A SAFE, GREEN METHOD TO PROCESS RED PHOSPHORUS
When it comes to making phosphorus compounds, chemists have traditionally relied on w ...
- Python next() 函数
Python next() 函数 Python 内置函数 描述 next() 返回迭代器的下一个项目. 语法 next 语法: next(iterator[, default]) 参数说明: ite ...
- linux下,MySQL默认的数据文档存储目录为/var/lib/mysql。
0.说明 Linux下更改yum默认安装的mysql路径datadir. linux下,MySQL默认的数据文档存储目录为/var/lib/mysql. 假如要把MySQL目录移到/home/data ...
- SVG脚本编程简介
本文主要介绍SVG的脚本编程,并分别给出放大.缩小,查询,鼠标事件等实例. 一. SVG简介 SVG,全称为Scalable Vector Graphics(可伸缩矢量图形).它是W3C制定的.用矢量 ...
- 12个优秀的国外Material Design网站案例
眼看2017年就快完了,你是不是还没完全搞懂Material Design呢?是嫌说明文档太长,还是觉得自己英文不好?都没关系,小编今天给大家整理了一份干货满满的学习笔记,并列举了一些国外的Mater ...
- linux 关键发行版及其关系图
- 现在有很多第三方的SDK来做直播,那么我们改选择哪一种?
现在大部分的都会借助第三方的直播技术,这样可以保证直播的质量,趣拍直播就很不错,SDK很好集成,芒果直播也在用.下面来分析一下趣拍直播的一些心得. 如何快速搭建一个完整的手机直播系统 在这个直播如火如 ...
- MongoDB管理与开发实战详解文摘
第1篇 基础篇 第1章 MongoDB简介 关系型数据库面临的问题:数据库并发负载高,海量数据存储与访问,数据库数据越来越大,事务管理的负担,关系型数据库读.写实时性的忽略,多表关联查询被弱化 第2章 ...
- CMake使用技巧集
1.注意CMake不允许出现相同的目标名称,即使是不同的目录下的CMakeLists.txt 2.将头文件搜索路径插入到其它的前面: include_directories(BEFORE /tmp) ...