【BZOJ3995】[SDOI2015]道路修建 线段树区间合并
【BZOJ3995】[SDOI2015]道路修建
Description
Input
第一行,两个整数N、M。
Output
对于每个询问操作,输出一行,表示你计算出的政府的最小开支。
Sample Input
1 2
2 1
3 1 2
Q 1 3
C 1 2 2 2 3
Q 2 3
Sample Output
5
HINT
对于全部的数据,1<=N, M<=60000,任何时刻任何一条专用道路的修建费用不超过10^4。
题解:第一次见到这题居然是在计蒜客上。。。一眼看出是线段树区间合并,但是真正写的时候。。。我被要维护的那一大坨东西征服了。于是去看了大爷的做法。
这里还是做一下大爷题解的注释吧:
先梳理出所有要维护的东西:区间端点,区间横边和,竖边个数,左侧(右)侧第一条竖边的值,左(右)侧竖边以及它左(右)侧的所有横边的最大值,MST的权值。
然后加入中间两条边,这样一定会形成环,找到环上最大的边mx。
如果这条边是左(右)侧的唯一一条竖边,则右(左)侧的最左(右)的竖边成为了区间中最左(右)侧的竖边,然后更新最大值。
否侧,直接更新最大值。
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #define lson x<<1
- #define rson x<<1|1
- using namespace std;
- const int maxn=60010;
- int v[maxn][3];
- struct node
- {
- int l,r,lsm,rsm,lm,rm,hm,sum,cnt;
- }s[maxn<<2];
- int n,m;
- char str[10];
- inline int max(int a,int b,int c) {return max(a,max(b,c));}
- inline int max(int a,int b,int c,int d) {return max(max(a,b),max(c,d));}
- inline node merge(node x,node y)
- {
- node z;
- z.l=x.l,z.r=y.r;
- int mh=max(v[x.r][0],v[x.r][1]),mx=max(x.rm,y.lm,mh);
- z.sum=x.sum+y.sum+v[x.r][0]+v[x.r][1]-mx,z.hm=max(x.hm,y.hm,mh),z.cnt=x.cnt+y.cnt;
- if(mx==x.rsm&&x.cnt==1)
- {
- z.lsm=y.lsm,z.rsm=y.rsm,z.lm=max(x.hm,y.lm,mh),z.rm=y.rm,z.cnt--;
- }
- else if(mx==y.lsm&&y.cnt==1)
- {
- z.lsm=x.lsm,z.rsm=x.rsm,z.lm=x.lm,z.rm=max(x.rm,y.hm,mh),z.cnt--;
- }
- else
- {
- z.lsm=x.lsm,z.rsm=y.rsm,z.lm=x.lm,z.rm=y.rm,z.cnt-=(mx==x.rsm||mx==y.lsm);
- }
- return z;
- }
- inline void init(node &x)
- {
- x.lsm=x.rsm=x.lm=x.rm=x.sum=v[x.l][2],x.hm=0,x.cnt=1;
- }
- void build(int l,int r,int x)
- {
- if(l==r)
- {
- s[x].l=l,s[x].r=r,init(s[x]);
- return ;
- }
- int mid=(l+r)>>1;
- build(l,mid,lson),build(mid+1,r,rson);
- s[x]=merge(s[lson],s[rson]);
- }
- void updata(int l,int r,int x,int a)
- {
- if(l==r)
- {
- init(s[x]);
- return ;
- }
- int mid=(l+r)>>1;
- if(a<=mid) updata(l,mid,lson,a);
- else updata(mid+1,r,rson,a);
- s[x]=merge(s[lson],s[rson]);
- }
- node query(int l,int r,int x,int a,int b)
- {
- if(a<=l&&r<=b) return s[x];
- int mid=(l+r)>>1;
- if(b<=mid) return query(l,mid,lson,a,b);
- if(a>mid) return query(mid+1,r,rson,a,b);
- return merge(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
- }
- inline int rd()
- {
- int ret=0,f=1; char gc=getchar();
- while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
- while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
- return ret*f;
- }
- int main()
- {
- n=rd(),m=rd();
- int i,a,b,c,d;
- for(i=1;i<n;i++) v[i][0]=rd();
- for(i=1;i<n;i++) v[i][1]=rd();
- for(i=1;i<=n;i++) v[i][2]=rd();
- build(1,n,1);
- for(i=1;i<=m;i++)
- {
- scanf("%s",str);
- if(str[0]=='C')
- {
- a=rd(),b=rd(),c=rd(),d=rd();
- if(a!=c) v[b][2]=rd(),updata(1,n,1,b);
- else
- {
- if(b>d) swap(b,d);
- if(a==1) v[b][0]=rd();
- else v[b][1]=rd();
- updata(1,n,1,b);
- }
- }
- else a=rd(),b=rd(),printf("%d\n",query(1,n,1,a,b).sum);
- }
- return 0;
- }//3 3 1 2 2 1 3 1 2 Q 1 3 C 1 2 2 2 3 Q 2 3
【BZOJ3995】[SDOI2015]道路修建 线段树区间合并的更多相关文章
- [bzoj3995] [SDOI2015]道路修建 线段树
Description 某国有2N个城市,这2N个城市构成了一个2行N列的方格网.现在该国政府有一个旅游发展计划,这个计划需要选定L.R两列(L<=R),修建若干条专用道路,使得这两列之间(包括 ...
- [SDOI2015]道路修建(线段树)
题意:给定2行n列的四连通带权网格图,支持修改边权和查询第[l,r]列的最小生成树 题解:这是一道好题,要么SDOI2019中n=2的20pts怎么会“我抄我自己”?(当然NOIP2018“我抄我自己 ...
- 【bzoj1018】[SHOI2008]堵塞的交通traffic 线段树区间合并+STL-set
题目描述 给出一张2*n的网格图,初始每条边都是不连通的.多次改变一条边的连通性或询问两个点是否连通. 输入 第一行只有一个整数C,表示网格的列数.接下来若干行,每行为一条交通信息,以单独的一行“Ex ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- HYSBZ 1858 线段树 区间合并
//Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- hdu3911 线段树 区间合并
//Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
随机推荐
- iOS怎样找到自己的沙盒
iOS怎样找到自己的沙盒 在ios开发我们会用到沙盒,因为自己对沙盒理解的不够,所以找不到沙盒文件在哪里,当然要知道路径了 比如我的路径 NSString* cachepath = [NSHomeDi ...
- selenuim-webdriver注解之@FindBy、@FindBys、@FindAll的区别
selenium-webdriver中获取页面元素的方式有很多,使用注解获取页面元素是其中一种途径, 方式有3种:@FindBy.@FindBys.@FindAll.下文对3中类型的区别和使用场景进行 ...
- 《从零開始学Swift》学习笔记(Day 57)——Swift编码规范之凝视规范:文件凝视、文档凝视、代码凝视、使用地标凝视
原创文章.欢迎转载.转载请注明:关东升的博客 前面说到Swift凝视的语法有两种:单行凝视(//)和多行凝视(/*...*/).这里来介绍一下他们的使用规范. 1.文件凝视 文件凝视就在每个文件开头加 ...
- linux 安装安装rz/sz 和 ssh
安装rz,sz yum install lrzsz; 安装ssh yum install openssh-server 查看已安装包 rpm -qa | grep ssh 更新yum源 1.备份 mv ...
- tcp/ip --- IP路由选择及子网寻址
IP路由选择 当一个IP数据包准备好了的时候,IP数据包(或者说是路由器)是如何将数据包送到目的地的呢?它是怎么选择一个合适的路径来"送货"的呢? 最特殊的情况是目的主机和主机直连 ...
- CentOS7下利用init.d启动脚本实现tomcat开机自启动
在之前的博文中已经对CentOS7下通过tomcat进行WEB系统的发布进行了介绍,今天将利用init.d启动脚本,将服务脚本加入到开机启动服务队列,实现tomcat服务的开机启动. 1. 环境准备 ...
- CSS3 not
AND (&&): .registration_form_right input:not([type="radio"]):not([type="check ...
- java的集合层次图
- D - Sigma Function 1~n内有多少个约数和为偶数
/** 题目:D - Sigma Function 链接:https://vjudge.net/contest/154246#problem/D 题意:求1~n内约数和为偶数的数的个数. 思路:一个数 ...
- iOS图片加水印效果的实现并保存至相冊
图片加水印效果的实现并保存至相冊 实现效果如图: project下载:githubproject下载链接 代码: - (void)viewDidLoad { [super viewDidLoad]; ...