HDU - 1540 Tunnel Warfare(线段树+区间合并)
题目链接:点击查看
题目大意:给定n个村庄,初始化全部连接为一条直线,需要依次执行m个操作,D表示摧毁第i个村庄的连接,R表示恢复最后一
个被摧毁的村庄的连接,Q表示询问包括本身在内,与第i个村庄相连接的有多少个村庄(间接连接也算)
题目分析:这个题需要用到区间合并的思想,并且用线段树来实现,应该算是个裸题了,把pushup的板子套进线段树里就OK,
不过这个题的query函数比较难写,我会在代码中写上相应注释来帮助理解,其余的函数就都是线段树的基础了
上代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
#include<cmath>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=5e4+100;struct Node
{int l,r;int ll,rr,all;
}tree[N<<2];void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].all=tree[k].ll=tree[k].rr=r-l+1;if(l==r)return;int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}void pushup(int k)//注意对三个参数上传的技巧
{tree[k].ll=tree[k<<1].ll;if(tree[k].ll==tree[k<<1].r-tree[k<<1].l+1)tree[k].ll+=tree[k<<1|1].ll;tree[k].rr=tree[k<<1|1].rr;if(tree[k].rr==tree[k<<1|1].r-tree[k<<1|1].l+1)tree[k].rr+=tree[k<<1].rr;tree[k].all=max(tree[k<<1].rr+tree[k<<1|1].ll,max(tree[k<<1].all,tree[k<<1|1].all));return;
}void update(int k,int pos,int val)
{if(tree[k].l==tree[k].r){tree[k].all=tree[k].ll=tree[k].rr=val;return;}int mid=(tree[k].r+tree[k].l)>>1;if(mid>=pos)update(k<<1,pos,val);elseupdate(k<<1|1,pos,val);pushup(k);
}int query(int k,int pos)
{if(tree[k].all==0)return 0;if(tree[k].l+tree[k].ll>pos)//判断是否在左区间 pos<左端点+左连续return tree[k].ll;if(tree[k].r-tree[k].rr<pos)//判断是否在右区间 pos>右端点-右连续 return tree[k].rr;if(pos>tree[k<<1].r-tree[k<<1].rr&&pos<tree[k<<1|1].l+tree[k<<1|1].ll)//判断是否在中间的区间
//右端点-右连续<pos<左端点+左连续return tree[k<<1].rr+tree[k<<1|1].ll;int mid=(tree[k].l+tree[k].r)>>1;if(mid>=pos)//如果上述条件不满足,继续向下递归判断return query(k<<1,pos);elsereturn query(k<<1|1,pos);
}int main()
{
// freopen("input.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)!=EOF){build(1,1,n);stack<int>st;while(m--){char s[5];scanf("%s",s);if(s[0]=='D'){int num;scanf("%d",&num);st.push(num);update(1,num,0);}else if(s[0]=='R'){if(!st.empty()){update(1,st.top(),1);st.pop();}}else{int num;scanf("%d",&num);cout<<query(1,num)<<endl;}}}return 0;
}
HDU - 1540 Tunnel Warfare(线段树+区间合并)相关推荐
- hdu 1540 Tunnel Warfare(线段树区间合并)
hdu 1540 Tunnel Warfare 记录每个节点的最大左连续值.最大右连续值.最大连续值,向上更新的是常规的区间合并处理方式 关键是想到如何去查询,如果查询节点落在左儿子节点的右连续段中, ...
- HDU 1540 Tunnel Warfare 线段树区间合并
Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...
- HDOJ1540 - Tunnel Warfare 线段树区间合并
HDOJ 1540 题目大意:给定两个整数N,M, 其中N表示一共有N个村庄,M代表有M次操作,操作有以下: 1. D x 销毁村庄x 2. Q x 询问与村庄x相邻的村庄总数 3. ...
- HDU - 3397 Sequence operation(线段树+区间合并)
题目链接:点击查看 题目大意:给定一个初始的数列,然后依次进行m次操作: 0 a b:将闭区间[a,b]内的点都变为0 1 a b:将闭区间[a,b]内的点都变为1 2 a b:将闭区间[a,b]内的 ...
- HDU - 2871 Memory Control(线段树+区间合并)好题!
题目链接:点击查看 题目大意:给定n个内存和m个操作,分别是: New x:从内存编号1开始向右查找,分配一个长度为x的空间,若找到输出区间的首地址,否则输出Reject New: Free x:释放 ...
- Tunnel Warfare(HDU1540+线段树+区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...
- HDU3308 线段树区间合并
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...
- 树链剖分——线段树区间合并bzoj染色
线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...
- SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并
Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...
最新文章
- 38.linux集合
- dyld: Library not loaded: @rpath/XCTest.framework/XCTest
- oracle 数字不用,oracle – Plsql将数字(货币)拼写为意大利货币而不用硬编码的翻译编号...
- mysql日期格式化季度_mysql中常用日期比较与计算函数
- 程序人生:给年轻程序员关于开发过程的10条忠告
- Gradle插件学习笔记(二)
- php redius,Linux下Redius的安装与部署详解
- 前端学到什么水平就可以去找工作呢?
- Hibernate之ID生成规则
- 一个 JS 框架需要做什么
- restController
- POJ1061 青蛙的约会 扩展欧几里得
- i510400和i59400f哪个好?有什么区别
- linux常用的解压缩文件的命令
- 细胞生物学-7-叶绿体和线粒体
- ARM发布Cortex-X1,是为了向苹果自研A系列处理器发起冲击吗?
- JavaScript: JSON基本概念带题解
- PhotoScan:为冲印的照片拍摄无眩光照片
- 关于Docker以及安装方法
- 偶像和粉丝关系该是什么样的?