hdu 1540 线段树
这题的意思是现在有一些村庄成一条直线排列,现在有三个操作,D:摧毁一个指定的村庄,Q:询问与指定村庄相连的村庄个数,
就是这个村庄向左和向右数村庄数量,遇到尽头或损坏的村庄为止,这个就是与这个村庄相连的村庄数量,当然,如果指定村庄已经被摧毁,则数量为0。R:把最后摧毁的那一个村庄恢复。在这里D操作和R操作都可以看成对线段树的单点修改,只是执行的操作不同,
最主要的是如何找和指定村庄相连的村庄数量,刚刚做的时候我很纠结,看了别人博客后... 我们可以定义一个max1和一个min1,表示这个区间里的最大值和最小值(max1初始化为-1,min1初始化为无穷大),这样一开始就是没有左右边界,如果某个村庄被摧毁,则把他的max1和min1都变成他的节点值,(自己体会一下下)
如果我们想找a村庄的的相连村庄数目,惯性思维是想一次性就把左右两个边界求出来,后来才发现我们其实可以用两次区间查询来分别找到a的左边界和右边界,query1(1,a,1)和query2(a,n,1)就是找区间1到a的的最大值和区间a到n的最小值,然后存一下这两个边界,最后相减。
具体可以看看代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
using namespace std;
#define inf 0x3f3f3f
struct node{
int l,r,min1,max1;
}str[*+];
stack<int>s;
int n,m,k,t,a,b;
int start,end1;
char ss[];
void build(int l,int r,int k)
{
str[k].l=l;
str[k].r=r;
str[k].max1=-;
str[k].min1=inf;
if(l==r)
{
return;
}
int mid=(l+r)/;
build(l,mid,k*);
build(mid+,r,k*+);
str[k].max1=max(str[k*].max1,str[k*+].max1);
str[k].min1=min(str[k*].min1,str[k*+].min1);
}
void change_point1(int k)//摧毁a点
{
if(str[k].l==str[k].r&&str[k].l==a)
{
str[k].max1=str[k].l;
str[k].min1=str[k].l;
return;
}
int mid=(str[k].l+str[k].r)/;
if(a<=mid)
change_point1(k*);
else
change_point1(k*+);
str[k].max1=max(str[k*].max1,str[k*+].max1);
str[k].min1=min(str[k*].min1,str[k*+].min1);
}
void change_point2(int k)//恢复a点
{
if(str[k].l==str[k].r&&str[k].l==a)
{
str[k].max1=-;
str[k].min1=inf;
return;
}
int mid=(str[k].l+str[k].r)/;
if(a<=mid)
change_point2(k*);
else
change_point2(k*+);
str[k].max1=max(str[k*].max1,str[k*+].max1);
str[k].min1=min(str[k*].min1,str[k*+].min1);
}
void query1(int l,int r,int k)//找a点的左边界
{
if(str[k].l>=l&&str[k].r<=r)
{
start=max(str[k].max1,start);
return;
}
int mid=(str[k].l+str[k].r)/;
if(l<=mid)
query1(l,r,k*);
if(r>mid)
query1(l,r,k*+);
}
void query2(int l,int r,int k)//找a点的右边界
{
if(str[k].l>=l&&str[k].r<=r)
{
end1=min(end1,str[k].min1);
return;
}
int mid=(str[k].l+str[k].r)/;
if(l<=mid)
query2(l,r,k*);
if(r>mid)
query2(l,r,k*+);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
build(,n,);
while(!s.empty())
s.pop();
for(int i=;i<m;i++)
{
scanf("%s",ss);
if(ss[]=='D')
{
scanf("%d",&a);
change_point1();
s.push(a);
}
else if(ss[]=='Q')
{
scanf("%d",&a);
start=-;
end1=inf;
query1(,a,);
query2(a,n,);
if(start==-)//特判一下
start=;
if(end1==inf)
end1=n+;
int ans=end1-start-; if(start==end1)
ans=;
printf("%d\n",ans);
}
else if(ss[]=='R')
{
if(!s.empty())
{
a=s.top();
change_point2();
s.pop();
}
}
}
}
return ;
}
hdu 1540 线段树的更多相关文章
- HDU - 1540 线段树的合并
这个题题意我大概解释一下,就是一开始一条直线,上面的点全是联通的,有三种操作 1.操作D把从左往右第x个村庄摧毁,然后断开两边的联通. 2.询问Q节点相联通的最长长度 3.把最后破坏的村庄重建. 这个 ...
- HDU 1540<线段树,区间并>
题目连接 参考 题意: 维护各个点的连续的最大连续长度. 思路: 主要是维护一个区间的三个变量ll,f[i].l为起点向右的最大连续 长度,rl:f[i].r为起点向左的最大连续长度,ml:[l,r] ...
- I - Tunnel Warfare HDU - 1540 线段树最大连续区间
题意 :一段区间 操作1 切断点 操作2 恢复最近切断的一个点 操作3 单点查询该点所在最大连续区间 思路: 主要是push_up : 设区间x 为母区间 x<<1 ,x< ...
- hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- hdu 3974 线段树 将树弄到区间上
Assign the task Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- hdu 3397 线段树双标记
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 4578 线段树(标记处理)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others) ...
- hdu 4533 线段树(问题转化+)
威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
随机推荐
- roadhog resolve alias 绝对路径 别名使用
新建 webpack.config.js 然后加入 如下代码 module.exports = (webpackConfig, env) => { // 别名配置 const data = we ...
- Navicat Premium 12安装与激活
https://www.jianshu.com/p/42a33b0dda9c 若使用Navicat Premium 12.1.10.0请转至Navicat Premium 12.1.10.0安装与激活 ...
- FireDac 组件说明二
FDUpdateSQL 生成添加,删除,修改SQL语句 TFDMetaInfoQuery 查询数据源信息 TFDEventAlerter 负责处理数据库事件通知 使用TFDEventAlerter类来 ...
- pandas 笔记
删除: del df["A"] # 原地修改 df.drop("a") # 返回修改后的新对象 df.drop(["a", " ...
- Vue router 的使用--初级
在说 VueRouter 之前,首先要弄明白vueRouter 是干什么的,有什么用 说出来其实很简单,就是一个模板替换的问题,当路由改变的时候,把和路由相关的模板显示出来,就是这么简单.但是,当我们 ...
- PDF文档的目录编辑与显示
为了更好的保护PDF文件,可以将其转换为图片的格式,再重新排版编辑. 使用压缩率更高的JPEG 2000图片格式更佳. ---------------------------------------- ...
- deb 和 rpm 后缀文件 区别和安装
https://blog.csdn.net/u010977122/article/details/52986217 下载一个ATOM 的deb的安装包
- IT蓝豹强烈推荐:符合1-2年工作经验,开发中的难点及相关优化:
IT蓝豹强烈推荐:符合1-2年工作经验,开发中的难点及相关优化: IT蓝豹 ------------------> sqlite数据库版本升级 1.sqlite升级步骤: 1.自己写一个类继承自 ...
- C# 根据Excel生成树
需求: 根据Excel生成树,Excel的某些节点为属性节点, 如: 列(桩号.构件编码.测试属性1) 是列(分项工程名称) 的属性,非节点. 列(桩号.构件编码.测试属性1) 以属性的方式存在 导入 ...
- 有关于分布式和SOA的理解
我的理解分布式和SOA都差不多,类似功能独立分开.举个例子,做一辆车,按照传统模式,先生产车架,然后生产车轮..然后一辆车完成.现在分布式就是生产车架与生产车轮分离,所有的材料 就是最后一次组装的时候 ...