线段树(二)STEP
线段树(二)
线段树例题整理
Part 1:题面
传送门:https://www.luogu.com.cn/problem/P6492(靠之前传送门放错了,暴露了我在机房逛B站的事实……
Part 2:思路整理
问题抽象化
题目中要求我们维护一个包含\(L、R\)序列,如果一个字序列中不包含连续的\(L\),或连续的\(R\),则称其满足要求
现在要求我们的程序支持两种操作:
1、单点修改,每次把\(L\)改为\(R\),把\(R\)改成\(L\)
2、区间查询,查询整个序列里满足条件的最长的字串
首先,我们可以把问题转换为这样:给定一个\(01\)串,每次对数列中的一个数执行异或操作,维护序列中最长的满足条件的串的长度
容易发现,本题的答案满足区间可合并性质,由一个\(0\)或\(1\)组成的串依次向上统计拼接,即可得到答案
所以我们使用线段树可以很方便的进行区间修改和整段区间查询操作
答案统计
现在考虑我们需要维护什么信息以及怎么自下而上统计这些信息
按照本人的垃圾思路,我们需要统计以下信息
\(1、\)最终答案:即为最长的满足条件的串
\(2、\)一个区间的最左端的字符:这决定了它可不可以与左边的区间合并
\(3、\)一个区间的最右端的字符:这决定了它可不可以与右边的区间合并
\(4、\)一个区间以最左端字符开始的最长的满足条件的串长度:这决定了它与左边的区间合并时产生的满足条件的串长度
\(5、\)一个区间以最右端字符开始的最长的满足条件的串长度:这决定了它与右边的区间合并时产生的满足条件的串长度
从下向上统计信息的时候,有以下八种情况:
这里为了简便,我们令\(ls,rs\)分别为指向左儿子的指针和指向右儿子的指针,\(lv,rv,mv\)分别为这个区间以最左端字符开始的最长满足条件串,这个区间以最右端字符开始的最长满足条件串和这个区间内最长的满足条件串,\(l,r\)则分别表示这个区间的左端点和右端点
请注意:
为了更加清晰的理解从下向上合并的操作,我们还需要引入一个概念——完全串:若该区间所代表的整个串是一个满足要求的串我们称为完全串,一个完全串有这些特性:
\(1、\)\(lc\neq rc\)
\(2、\)\(lv=rv=mv=(r-l+1)\)
显然完全串的统计方式和普通串的统计方式应该不同
我们用这样一个函数来判断这个区间是不是完全串:
inline bool copst(const int L,const int R,const int Len) { return (Len==R-L+1); }//是否为完全串
//下面我们用copst(ls||rs)==true||false代表左右儿子是否是完全串
我们用这个函数返回三个参数的最大值
inline int smax(const int a,const int b,const int c){
const int d=max(a,b);
return max(c,d);
}
\(1、copst(ls)=true,copst(rs)=true,ls\rightarrow rc\neq rs\rightarrow lc\)(可以合并)
\(lv=r-l+1,rv=r-l+1,mv=r-l+1\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(2、copst(ls)=true,copst(rs)=true,ls\rightarrow rc=rs\rightarrow lc\)(不能合并)
\(lv=ls\rightarrow lv,rv=rs\rightarrow rv,mv=max(ls\rightarrow mv,rs\rightarrow mv)\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(3、copst(ls)=false,copst(rs)=true,ls\rightarrow rc\neq rs\rightarrow lc\)(可以合并)
\(lv=ls\rightarrow lv,mv=smax(ls\rightarrow mv,ls\rightarrow rv+rs\rightarrow lv,rs\rightarrow mv),rv=ls\rightarrow rv+rs\rightarrow rv\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(4、copst(ls)=false,copst(rs)=true,ls\rightarrow rc=rs\rightarrow lc\)(不能合并)
\(lv=ls\rightarrow lv,mv=max(ls\rightarrow mv,rs\rightarrow mv),rv=rs\rightarrow rv\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(5、copst(ls)=true,copst(rs)=false,ls\rightarrow rc\neq rs\rightarrow lc\)(可以合并)
\(lv=ls\rightarrow mv+rs\rightarrow lv,mv=smax(ls\rightarrow mv,ls\rightarrow rv+rs\rightarrow lv,rs\rightarrow mv),rv=rs\rightarrow rv\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(6、copst(ls)=true,copst(rs)=false,ls\rightarrow rc=rs\rightarrow lc\)(不能合并)
\(lv=ls\rightarrow lv,mv=max(ls\rightarrow mv,rs\rightarrow mv),rv=rs\rightarrow rv\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(7、copst(ls)=false,copst(rs)=false,ls\rightarrow rc\neq rs\rightarrow lc\)(可以合并)
\(lv=ls\rightarrow mv+rs\rightarrow mv,mv=ls\rightarrow mv+rs\rightarrow mv,rv=ls\rightarrow mv+rs\rightarrow mv\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
\(8、copst(ls)=false,copst(rs)=false,ls\rightarrow rc=rs\rightarrow lc\)(可以合并)
\(lv=ls\rightarrow lv,mv=max(ls\rightarrow mv,rs\rightarrow mv),rv=rs\rightarrow rv\)
\(lc=ls\rightarrow lc,rc=rs\rightarrow rc\)
Part 3:\(Code\)
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=200005;
int n,q;
inline int smax(const int a,const int b,const int c){
const int d=max(a,b);
return max(d,c);
}
struct sag{//这里作者又拼错了qwq,凑合看叭
int lc,rc,lv,rv,mv;
int l,r;
sag *ls,*rs;
inline void push_up(){
bool liscop=copst(ls->l,ls->r,ls->mv);
bool riscop=copst(rs->l,rs->r,rs->mv);
if(liscop==1&&riscop==0&&ls->rc!=rs->lc){
lv=ls->mv+rs->lv;
mv=smax(ls->mv,ls->rv+rs->lv,rs->mv);
rv=rs->rv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==1&&riscop==0&&ls->rc==rs->lc){
lv=ls->lv;
mv=max(ls->mv,rs->mv);
rv=rs->rv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==0&&riscop==1&&ls->rc!=rs->lc){
lv=ls->lv;
mv=smax(ls->mv,ls->rv+rs->lv,rs->mv);
rv=ls->rv+rs->rv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==0&&riscop==1&&ls->rc==rs->lc){
lv=ls->lv;
mv=max(ls->mv,rs->mv);
rv=rs->rv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==0&&riscop==0&&ls->rc!=rs->lc){
lv=ls->lv;
mv=smax(ls->mv,ls->rv+rs->lv,rs->mv);
rv=rs->rv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==0&&riscop==0&&ls->rc==rs->lc){
lv=ls->lv;
mv=max(ls->mv,rs->mv);
rv=rs->rv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==1&&riscop==1&&ls->rc!=rs->lc){
lv=ls->mv+rs->mv;
mv=ls->mv+rs->mv;
rv=ls->mv+rs->mv;
lc=ls->lc;
rc=rs->rc;
}
if(liscop==1&&riscop==1&&ls->rc==rs->lc){
lv=ls->lv;
mv=max(ls->mv,rs->mv);
rv=rs->rv;
lc=ls->lc;
rc=rs->rc;
}
}
inline bool copst(const int L,const int R,const int Len) { return (Len==R-L+1); }//是否为完全串
inline bool in_range(const int L,const int R) { return (L<=l)&&(r<=R); }
inline bool outof_range(const int L,const int R) { return (r<L)||(R<l); }
void update(const int L,const int R){
if(in_range(L,R)){
lc=(lc==1)?0:1;
rc=lc;
lv=rv=mv=1;
}else if(!outof_range(L,R)){
ls->update(L,R);
rs->update(L,R);
push_up();//由孩子向父亲统计信息
}
}
}*rot;
sag byte[maxn<<1],*pool=byte;
sag* New(const int L,const int R){
sag *u=pool++;
u->l=L,u->r=R;
if(L==R){
u->ls=u->rs=NULL;
u->lc=u->rc=0;
u->mv=u->lv=u->rv=1;
}else{
int Mid=(L+R)>>1;
u->ls=New(L,Mid);
u->rs=New(Mid+1,R);
u->push_up();
}
return u;
}
int main(){
scanf("%d%d",&n,&q);
rot=New(1,n);
for(int x,i=0;i<q;i++){
scanf("%d",&x);
rot->update(x,x);
printf("%d\n",smax(rot->lv,rot->rv,rot->mv));
}
return 0;
}
线段树(二)STEP的更多相关文章
- UVA 11297 线段树套线段树(二维线段树)
题目大意: 就是在二维的空间内进行单个的修改,或者进行整块矩形区域的最大最小值查询 二维线段树树,要注意的是第一维上不是叶子形成的第二维线段树和叶子形成的第二维线段树要 不同的处理方式,非叶子形成的 ...
- BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)
题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...
- 洛谷 P4088 [USACO18FEB] Slingshot P(线段树+二维数点)
题目链接 题意:有一个数轴,上面有 \(n\) 个传送门,使用第 \(i\) 个传送门,你可以从 \(x_i\) 走到 \(y_i\),花费的时间为 \(t_i\) 秒.你的速度为 \(1\) 格/秒 ...
- CodeForces 242E - XOR on Segment 二维线段树?
今天练习赛的题....又是线段树的变换..拿到题我就敲了个点更新区间查询的..果断超时...然后想到了可以将每个数与合表示成不进位的二进制数..这样就可以区间进行更新了..比赛的时候写搓了..刚重写了 ...
- Luck and Love(二维线段树)
Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- POJ2155 Matrix 二维线段树
关键词:线段树 二维线段树维护一个 维护一个X线段的线段树,每个X节点维护一个 维护一个Y线段的线段树. 注意,以下代码没有PushDownX.因为如果要这么做,PushDownX时,由于当前X节点的 ...
- Wannafly Winter Camp 2020 Day 5I Practice for KD Tree - 二维线段树
给定一个 \(n \times n\) 矩阵,先进行 \(m_1 \leq 5e4\) 次区间加,再进行 \(m_2 \leq 5e5\) 次询问,每次询问要求输出矩形区间内的最大数.\(n \leq ...
- HDU 3642 Get The Treasury 线段树+分层扫描线
http://www.acmerblog.com/hdu-3642-get-the-treasury-6603.html 学习:三维就是把竖坐标离散化分层,每一层进行线段树二维面积并就好了
- [IOI2018]狼人——kruskal重构树+可持久化线段树
题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...
- HDU1823-Luck and Love-二维线段树(模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=1823 好吧,给这题跪了. ..orz.... 一道非常基础的二维线段树的模板题: 可是细节非常多:尤 ...
随机推荐
- windows下nginx问题:[crit] 796#7096: *1 GetFileAttributesEx() "F: ginx-1.12.2\html\dist" failed (123: The filename, directory name, or volume label syntax is incorrect), client: 127.0.0.1, server: localho
错误信息: 2019/09/09 13:54:37 [crit] 796#7096: *1 GetFileAttributesEx() "F: ginx-1.12.2\html\dist&q ...
- Socket通信,基本方法介绍
Socket是什么呢? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口. 在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口 ...
- PHP imagecolorclosesthwb - 取得与指定的颜色最接近的色度的黑白色的索引
imagecolorclosesthwb — 取得与指定的颜色最接近的色度的黑白色的索引.高佣联盟 www.cgewang.com 语法 int imagecolorclosesthwb (s res ...
- Prism.Interactivity 和 Prism.Modularity 介绍
Prism.Interactivity: 主要用来截取View即界面的一些处理,而这些功能通过vm 不好实现,只能用 CommandBehaviorBase 来截取处理,特别是在处理界面异常很有用. ...
- JavaWeb基础Day17 (JSP EL表达式 jstl标签库 beanutil工具类)
JSP jsp的实质就是指在html界面中嵌入Java代码 jsp脚本 <% Java代码 %> 相当于写在service方法中. <%=java 变量或者表达式 %> ...
- Java中15种锁的介绍
作者:搜云库技术团队 原文:https://segmentfault.com/a/1190000017766364 1. Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观 ...
- MVC + EFCore 项目实战 - 数仓管理系统9 - 数据源管理完结篇
我们完成数据源管理的剩余部分:点击表名,预览表中数据. 我们需要完成的是下图的方框部分. 考虑到这块以后可能复用,我们将她独立出来,做成 view component. 新建 view compone ...
- 安卓APP开发的初步了解
今天成功安装了Android Studio 并且对APP的开发框架结构进行了初步了解 如上图:app基本结构情况 下面来仔细解释一下各个方面目录的作用 首先 manifests目录:包含Android ...
- C/C++陷阱与套路,当年就是折在这些地儿…
摘要:本文结合作者的工作经验和学习心得,对C++语言的一些高级特性,做了简单介绍:对一些常见的误解,做了解释澄清:对比较容易犯错的地方,做了归纳总结:希望借此能增进大家对C++语言了解,减少编程出错, ...
- 微信商户H5支付申请不通过被驳回,拒绝原因提示:网站存在不实内容或不安全信息
一.H5支付简介及使用场景说明 H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付.主要用于触屏版的手机浏览器请求微信支付 ...