/*
hdu-1540 题意:一个线段,长度为n,三种操作,Dx,挖掉某个点;R,恢复最近被挖掉的点;Qx查询该点所在的连续区间的长度;
树的节点维护三个变量,该节点左边界开始连续的个数ll,右边界开始向左连续的个数rl,(在该区间内),该区间内最大的连续区间的长度ml;
最后一个变量是为了方便判断,主要的还是前两个;
修改的时候先是深入单点修改单点信息,然后回溯上来更父结点,更新的时候有点复杂;
查询的时候借助ml的长度减少计算量,快速返回;
区间合并;
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
struct Node
{
int l,r,ll,rl,ml;
}tr[];
void build(int rt,int l,int r)
{
tr[rt].l=l;
tr[rt].r=r;
tr[rt].ll=tr[rt].rl=tr[rt].ml=r-l+;
if(l==r)
return ;
int mid=(l+r)/;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
}
void Update(int rt,int l,int r,int t,int val)//t是要改的点;
{
if(l==r) //找到单点;
{
if(val==)
{
tr[rt].ll=tr[rt].rl=tr[rt].ml=;//改单点的信息;
}
else
{
tr[rt].ll=tr[rt].rl=tr[rt].ml=;
}
return ;
}
int mid=(l+r)/;//二分查找区间;
if(t<=mid)
{
Update(rt<<,l,mid,t,val);
}
else
{
Update(rt<<|,mid+,r,t,val);
}
// pushup操作;
tr[rt].ll=tr[rt<<].ll; //左子树的左侧边界的值给父节点;
tr[rt].rl=tr[rt<<|].rl; //右子树的有边界的值给父结点;
tr[rt].ml=max(tr[rt<<].ml,tr[rt<<|].ml); //左右子树的最大连续数;
tr[rt].ml=max(tr[rt].ml,tr[rt<<].rl+tr[rt<<|].ll); //两个子树的交接处的最大连续数;
if(tr[rt<<].ll==mid-l+)
tr[rt].ll+=tr[rt<<|].ll; //如果左子树是全连续的,就更新父节点的左边界最大连续数;
if(tr[rt<<|].rl==r-mid) //如果右子树是连续的,就更新父结点的有边界的最大连续数;
tr[rt].rl+=tr[rt<<].rl;
}
int Query(int rt,int l,int r,int t)//查询与这个点连接的最长序列;
{
if(l==r||tr[rt].ml==||tr[rt].ml==r-l+) //如果找到单点,或该区间全空,或该区间全满;就返回;
return tr[rt].ml;
int mid=(l+r)/;
if(t<=mid) //如果该点在左子树上
{
if(t>=tr[rt<<].r-tr[rt<<].rl+) //如果该点是在左子树右边界点连续范围,就进入左子树继续搜索该点并加上搜索右子树的左边界那个点的结果;
return Query(rt<<,l,mid,t)+Query((rt<<)|,mid+,r,mid+);
else
return Query(rt<<,l,mid,t); //如果不再右连续块内就进左子树继续搜索;
}
else//右子树;
{
if(t<=tr[rt<<|].l+tr[rt<<|].ll-) //在右子树的左侧连续的部分内,就加上左子树上的数据,左子树右边界的(不能用有子树的数据因为那不是全部的数据);
return Query(rt<<|,mid+,r,t)+Query(rt<<,l,mid,mid);
else
return Query(rt<<|,mid+,r,t);
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF&&n&&m)
{
memset(tr,,sizeof(tr));
stack<int > z;
build(,,n);
for(int i=;i<m;i++)
{
char a[];
scanf("%s",a);
if(a[]=='D')
{
int x;
scanf("%d",&x);
z.push(x);
Update(,,n,x,); //0代表删除操作;
}
else if(a[]=='R')
{
if(!z.empty())
{
int x=z.top();
z.pop();
Update(,,n,x,); //1代表回复操作;
}
}
else if(a[]=='Q')
{
int x;
scanf("%d",&x);
int ans=Query(,,n,x);
printf("%d\n",ans);
}
}
}
return ;
}

kb-09-线段树--区间合并比较繁的更多相关文章

  1. HYSBZ 1858 线段树 区间合并

    //Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...

  2. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  3. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  4. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  5. HDU 3911 Black And White(线段树区间合并+lazy操作)

    开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...

  6. hdu3911 线段树 区间合并

    //Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  7. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  8. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

  9. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  10. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

随机推荐

  1. UVA 11134 FabledRooks 传说中的车 (问题分解)

    摘要:贪心,问题分解. 因为行列无关,所以这个二维问题可以分解成两个一维问题. 优先队列实现:类似区间点覆盖的问题,先按照左端点排序,相同然后在按右端点排序(灵活性小的优先选).最优的选法,当然是要使 ...

  2. 如何使用动画库animate.css

    animate.css是一个CSS3动画库,里面预设了抖动(shake).闪烁(flash).弹跳(bounce).翻转(flip).旋转(rotateIn/rotateOut).淡入淡出(fadeI ...

  3. Unity调用Windows窗口句柄,选择文件和目录

    T:2019-6-25 10:06:59 C:Scatt Kang using System; using System.Collections; using System.Collections.G ...

  4. PAT (Basic Level) Practise (中文)- 1011. A+B和C (15)

    http://www.patest.cn/contests/pat-b-practise/1011 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1 ...

  5. ValidForm验证表单

    在做项目时,要求熟悉项目中验证表单的插件,所以学习一下validForm这个插件 http://validform.rjboy.cn/document.html#validformObject

  6. Object类 任何类都是object类的子类 用object对象接收数组 object类的向上向下转型

    任何类都是object类的子类 用object对象接收数组 object类的向上向下转型

  7. python中的sort、sorted排序

    我们通常会遇到对数据库中的数据进行排序的问题,今天学习一下对列表和字典的排序方法. 列表 第一种:内建方法sort sort()对列表排序是永久性的排序. 用法:sort(*, key=None, r ...

  8. CentOS7下Mysql5.7主从数据库配置

    本文配置主从使用的操作系统是Centos7,数据库版本是mysql5.7. 准备好两台安装有mysql的机器(mysql安装教程链接) 主数据库配置 每个从数据库会使用一个MySQL账号来连接主数据库 ...

  9. DELL PowerEdge R620安装Windows server(你想将windows安装在何处”找不到任何本地磁盘,“找不到驱动器”)已解决!

    你可能碰到过DELL服务器上安装Windows server系列系统时无法识别或找不到硬盘的问题,对于DELL PowerEdge11-14代机器的,大家可以采用DELL的Lifecycle cont ...

  10. 【Maven】 (请使用 -source 8 或更高版本以启用 lambda 表达式)

    在使用mvn install编译maven项目时,报了 “ (请使用 -source 8 或更高版本以启用 lambda 表达式)”错误,是因为设置的maven默认jdk编译版本太低的问题. 可使用两 ...