/*
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. C基础的练习集及测试答案(16-30)

    16.(课堂)输入一个年份(正整数),判断这年是否是闰年.闰年判断标准:年份能被4整除:如若遇到100的倍数,则需判断年份能否被400整除.(逢4一闰,逢百不闰,逢400又闰) #if 0 .(课堂) ...

  2. [神经网络]一步一步使用Mobile-Net完成视觉识别(三)

    1.环境配置 2.数据集获取 3.训练集获取 4.训练 5.调用测试训练结果 6.代码讲解 本文是第三篇,获取tfboard训练集. 前面我们拿到了所有图片对应的标注信息的xml文件,现在我们需要先把 ...

  3. css设置禁止文字被选中

    // 禁止文字被鼠标选中 moz-user-select: -moz-none; -moz-user-select: none; -o-user-select:none; -khtml-user-se ...

  4. fork新建进程

    #include <sys/types.h>#include<sys/wait.h>#include<unistd.h>#include<stdio.h> ...

  5. IntelliJ IDEA java设置程序运行时内存

    Run/Edit Configurations   Configuration/VM options  例如:设置运行内存为:-Xmx3m -Xms3m

  6. 201621123080《JAVA程序设计》第八周学习总结

    作业08-集合 1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 根据代码,首先在源数组里找到下标,若下标符合>=0 ...

  7. 腾讯云Ubuntu服务器修改root密码

    1.修改root密码 执行以下命令,按照提示修改密码 sudo passwd root 2.修改ssh配置 执行以下命令 sudo vi /etc/ssh/sshd_config 找到 PermitR ...

  8. Thinkphp5 的常用连式查询

    目录 取出表中改字符串前两位等于01的数据 按主键查询 不按主键查 JOIN方法 的左右连接 not in 方法 like 查询 where 按条件筛选查询 取出表中改字符串前两位等于01的数据 $p ...

  9. Linux入门学习笔记1:VI常用命令

    常用命令 yy 复制 p 黏贴 shift+v 多行选中 shift+ctrl+< 左移 shift+ctrl+> 右移 ndd 删除光标所在行及其后n-1行 i 进入编辑状态 esc 退 ...

  10. MySQL-状态Waiting on empty queue引申

    MySQL 事件调度器示例演示 我们大家都知道MySQL 事件调度器是在 MySQL 5.1 中新生的一个较为特殊的功能,其可以作为定时任务调度器,来取代部分原先只能用操作系统任务调度器才能完成的定时 ...