P6492 [COCI2010-2011#6] STEP (线段树)

这篇博客探讨了如何利用线段树解决一道求最长01/10串的题目。文章详细分析了线段树在维护区间信息时的合并策略,包括如何合并子区间答案以及如何在pushup过程中维护前缀答案。作者强调了在区间合并时注意答案的维护对于理解线段树的重要性。
摘要由CSDN通过智能技术生成

题目链接
在这里插入图片描述
在这里插入图片描述
我们先规定L为0 R为1,题目就是求最长的01/10串

从题意来看,类似单点修改 区间查询,于是思考能否用线段树来维护某些东西,从而在logn时间内完成查询。

我们令tree[rt].ans 表示rt对应区间的答案,也就是最长的01/10串

我们考虑左右两个子区间 [l,mid] 、[mid+1,r] 的合并的若干种情况:

①当左子区间右端点等于右子区间左端点 :此时根节点答案只能是左右子树答案中的最大值。

tree[rt].ans=max( tree[lc(rt)].ans , tree[rc(rt)].ans )

(到这里我们线段树需要维护的信息有:1、区间答案 2、左右端点的值)

②当左子区间右端点不等于右子区间左端点:此时此时根节点答案是左右子树答案、合并后中间段产生的答案三者中的最大值。
那么问题来了,合并后中间段的答案怎么求呢? 其实就等于左子树后缀答案加上右子树前缀答案 。

那么到这里线段树这需要维护的信息还要加上区间前缀中最长的01/10串的长度以及后缀中最长的01/10串的长度

但是pushup过程中前缀答案该怎么维护呢?也分两种情况
①:当左子树的前缀长度小于左子区间,那么rt的前缀答案直接继承左子树的前缀答案
②:当左子树的前缀长度等于左子区间,也就是左子区间整个就是01/10串,此时如果右子区间左端点等于左子区间右端点,那么rt的前缀也是直接继承左子树的前缀答案, 否则还要加上右子树前缀答案。

可能有点绕,看代码和注释就很明显啦

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5+7;
const ll inf = 34359738370;
//给定01串,q次修改 每次翻转一个位置。 每次修改要输出此时最长的不含连续元素的子串长度(01串/10串的长度)
//线段树维护以下信息:
//1、区间最长的01/10串长度 2、区间左右端点 3、前缀中最长答案 4、后缀中最长答案
struct node
{
   
    int ans;//区间答案
    int pans,sans,lv,rv;//前缀中最长答案 后缀最长答案 左端点 右端点
}tree[maxn<<2];
int n,m;
inline int lc(int &rt)
{
   
    return rt<<1;
}
inline int rc(int &rt)
{
   
    return rt<<1 | 1;
}
inline void pushup(int &rt,int l,int r)
{
   
    int mid=
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值