UVALive - 4108 SKYLINE (吉司机线段树)
题意:在一条直线上依次建造n座建筑物,每座建筑物建造完成后询问它在多长的部分是最高的。
比较好想的方法是用线段树分别维护每个区间的最小值mi和最大值mx,当建造一座高度为x的建筑物时,若mi>x则答案无贡献,直接退出,若mx<=x则区间赋值为x,答案加上区间长度。其他情况需要继续递归搜索。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+,inf=0x3f3f3f3f;
int n,mx[N<<],mi[N<<],lz[N<<];
ll ans;
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
void pu(int u) {mx[u]=max(mx[ls],mx[rs]),mi[u]=min(mi[ls],mi[rs]);}
void change(int u,int x) {mx[u]=mi[u]=lz[u]=x;}
void pd(int u) {if(~lz[u])change(ls,lz[u]),change(rs,lz[u]),lz[u]=-;}
void build(int u=,int l=,int r=) {
lz[u]=-;
if(l==r) {mx[u]=mi[u]=; return;}
build(ls,l,mid),build(rs,mid+,r),pu(u);
}
void upd(int L,int R,int x,int u=,int l=,int r=) {
if(l>R||r<L||x<mi[u])return;
if(l>=L&&r<=R&&x>=mx[u]) {ans+=r-l+,change(u,x); return;}
pd(u),upd(L,R,x,ls,l,mid),upd(L,R,x,rs,mid+,r),pu(u);
}
int main() {
int T;
for(scanf("%d",&T); T--;) {
build(),ans=;
scanf("%d",&n);
while(n--) {
int l,r,x;
scanf("%d%d%d",&l,&r,&x),r--;
upd(l,r,x);
}
printf("%lld\n",ans);
scanf("");
}
return ;
}
这种方法对于随机数据是比较快的,但会被一些极端的数据卡成n^2,比如先来个[1,2,100000],[3,4,100000],...(每两个位置建一座很高的建筑物),然后来一堆[1,100000,1],[1,100000,2],...,遇到这种情况就GG了。
解决方法是改成吉司机线段树(Segment tree beats),稳定nlogn~
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+,inf=0x3f3f3f3f;
int n,mi[N<<],se[N<<],nmi[N<<],lz[N<<];
ll ans;
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
void pu(int u) {
mi[u]=min(mi[ls],mi[rs]),se[u]=max(mi[ls],mi[rs]);
se[u]=se[u]==mi[u]?min(se[ls],se[rs]):min(se[u],min(se[ls],se[rs]));
nmi[u]=(mi[ls]==mi[u]?nmi[ls]:)+(mi[rs]==mi[u]?nmi[rs]:);
}
void change(int u,int x) {mi[u]=lz[u]=x;}
void pd(int u) {
if(~lz[u]) {
if(mi[ls]<lz[u])change(ls,lz[u]);
if(mi[rs]<lz[u])change(rs,lz[u]);
lz[u]=-;
}
}
void build(int u=,int l=,int r=) {
lz[u]=-;
if(l==r) {mi[u]=,se[u]=inf,nmi[u]=; return;}
build(ls,l,mid),build(rs,mid+,r),pu(u);
}
void upd(int L,int R,int x,int u=,int l=,int r=) {
if(l>R||r<L||mi[u]>x)return;
if(l>=L&&r<=R&&se[u]>x) {change(u,x),ans+=nmi[u]; return;}
pd(u),upd(L,R,x,ls,l,mid),upd(L,R,x,rs,mid+,r),pu(u);
}
int main() {
int T;
for(scanf("%d",&T); T--;) {
build(),ans=;
scanf("%d",&n);
while(n--) {
int l,r,x;
scanf("%d%d%d",&l,&r,&x),r--;
upd(l,r,x);
}
scanf("");
printf("%lld\n",ans);
}
return ;
}
UVALive - 4108 SKYLINE (吉司机线段树)的更多相关文章
- HDU - 5306 Gorgeous Sequence (吉司机线段树)
题目链接 吉司机线段树裸题... #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3 ...
- BZOJ4355: Play with sequence(吉司机线段树)
题意 题目链接 Sol 传说中的吉司机线段树??感觉和BZOJ冒险那题差不多,就是强行剪枝... 这题最坑的地方在于对于操作1,$C >= 0$, 操作2中需要对0取max,$a[i] > ...
- bzoj4355 Play with sequence(吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 赋值为\(x\) \(2.\)区间\([L,R]\) 赋值为\(max(a[i] + x, 0)\) \(3.\)区间 ...
- bzoj5312 冒险(吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 按位与\(x\) \(2.\)区间\([L,R]\) 按位或\(x\) \(3.\)区间\([L,R]\) 询问最大值 ...
- bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)给一个区间\([L,R]\) 加上一个数\(x\) \(2.\)把一个区间\([L,R]\) 里小于\(x\) 的数变成\(x\) \(3.\ ...
- HDU - 6315 吉司机线段树
题意:给出a,b数组,区间上两种操作,给\(a[L,R]\)+1s,或者求\(\sum_{i=l}^{r}a_i/b_i\) 一看就知道是吉司机乱搞型线段树(低配版),暴力剪枝就好 维护区间a的最大值 ...
- HDU 5306 吉司机线段树
思路: 后面nlogn的部分是伪证... 大家可以构造数据证明是这是nlog^2n的啊~ 吉老司机翻车了 //By SiriusRen #include <cstdio> #include ...
- hdu6521 吉司机线段树
http://acm.hdu.edu.cn/showproblem.php?pid=6521 待填 代码 #include<bits/stdc++.h> #define ls o<& ...
- Petrozavodsk Winter-2018. AtCoder Contest. Problem I. ADD, DIV, MAX 吉司机线段树
题意:给你一个序列,需要支持以下操作:1:区间内的所有数加上某个值.2:区间内的所有数除以某个数(向下取整).3:询问某个区间内的最大值. 思路(从未见过的套路):维护区间最大值和区间最小值,执行2操 ...
随机推荐
- Python学习札记(五) Basic2 字符串和编码
参考:字符串和编码 Note A.字符编码 1.计算机处理文本 == 将文本转换为二进制 => 处理 2.8 bit(比特) = 1 byte(字节) 一个字节所能表示的最大的十进制整数是255 ...
- SpringBoot中使用log4j日志
一:引入jar包 使用SpringBoot创建项目的时候,pom文件引入了spring-boot-starter,其中包含了spring-boot-starter-logging,该依赖内容就是Spr ...
- sa learning
后缀数组之前一直在给队友搞,但是这个类太大了,预感到青岛八成会有,于是自己也学习一下,记录一下做题的历程 所用的模板暂时来自于队友的倍增nlogn da算法 int t1[maxn] , t2[max ...
- 不一样的入门:看C# Hello World的17种写法
摘要:本文针对不同阶段.不同程度的C#学习者,介绍了C# Hello World的17种不同写法,希望会对大家有所帮助.(C# Hello World写法入门.C# Hello World写法进阶.C ...
- ORM框架greenDao 2 (用于了解旧版本的使用方法,目前最新版本为3.2.2,使用注释的方式来生成)
摘要: Android中对SQLite数据库使用,是一件非常频繁的事情.现今,也有非常多的SQLite处理的开源框架,其中最著名的greenDao,它以占用资源少,处理效率高等特点,成为优秀的ORM框 ...
- 正确的使用pod install 和 pod update
pod install 在项目中第一次使用CocoaPods, 进行安装的时候使用这个命令. 在Podfile中增加或删除某个pod后, 也是使用这个命令. 而不是pod update. 每次运行po ...
- FTRL 使用tensorflow的实现
import tensorflow as tfimport numpy as npfrom sklearn import metricsfrom sklearn.datasets import loa ...
- [Vue]Vue语法糖v-bind、v-on
语法糖 :是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发,简化代码是书写. Vue.js的v-bind和v-on指令都提供了语法糖,也可以说是缩写. 1.v-bind可以省略, ...
- SEA 教程
Sina App Engine(SAE)教程(11)- Yaf使用 Sina App Engine(SAE)入门教程(10)- Cron(定时任务)使用 Sina App Engine(SAE)入门教 ...
- Opencv+pycharm+anaconda配置
最简便的方法,没有之一 首先下载annconda:(不要从官网下,还要FQ,还要慢) https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 请注 ...