hdu just a hook 线段树
2013-09-27 16:33
232 查看
在网上看到很多人写线段树的专题,我觉得线段树如此流行不仅仅是因为ACM题目里有它,而且它的实际应用价值也很高。
这道题的大意是你可以将钩子的某一段区间变为等级1(铜钩),等级2(银钩),或等级3(金钩)的钩子,问你在若干次变换后,整个钩子的值是多少。
我的想法是建一颗线段树,树的每一个节点保存有左右端点的值,这一段长度的等级(初值为0),没插入一条线段,就在插入的过程中判断经过的线段有没有被覆盖过(这就是为什么初值为0的原因),如果有被覆盖过,就把这条线段打破(就是将这条线段重新置为0,表示为没覆盖),然后再将待插入的线段继续往下更新,将打破的这条线段的余下部分更新下去(个人觉得这思路很挫。。。但是我只能想到这么做了。。。)。
比如说开始我把(1,10)的区间变为等级3,现在我要将(4,6)的区间变为等级2,那么我就先正常插入(4,6)这个线段,插入过程中先碰到(1,10)这个线段,发现这个线段已经被覆盖过了(不为0),就把(1,10)置为0,然后把(1,10)拆成3段(1,3)值为3,(4,6)值为2,(7,10)值为3,分别从当前位置插入这三条线段,直到插入的线段和遇到的线段表示的长度一致的时候就停下,并更新这一条线段。
这道题的大意是你可以将钩子的某一段区间变为等级1(铜钩),等级2(银钩),或等级3(金钩)的钩子,问你在若干次变换后,整个钩子的值是多少。
我的想法是建一颗线段树,树的每一个节点保存有左右端点的值,这一段长度的等级(初值为0),没插入一条线段,就在插入的过程中判断经过的线段有没有被覆盖过(这就是为什么初值为0的原因),如果有被覆盖过,就把这条线段打破(就是将这条线段重新置为0,表示为没覆盖),然后再将待插入的线段继续往下更新,将打破的这条线段的余下部分更新下去(个人觉得这思路很挫。。。但是我只能想到这么做了。。。)。
比如说开始我把(1,10)的区间变为等级3,现在我要将(4,6)的区间变为等级2,那么我就先正常插入(4,6)这个线段,插入过程中先碰到(1,10)这个线段,发现这个线段已经被覆盖过了(不为0),就把(1,10)置为0,然后把(1,10)拆成3段(1,3)值为3,(4,6)值为2,(7,10)值为3,分别从当前位置插入这三条线段,直到插入的线段和遇到的线段表示的长度一致的时候就停下,并更新这一条线段。
#include<stdio.h> struct SeqTree { int l,r,v; }a[400005]; int n; void build(int l,int r,int pos) { a[pos].l = l; a[pos].r = r; a[pos].v = 0; if(l == r) return ; int mid = (l + r) >> 1; build(l,mid,(pos << 1) + 1); build(mid + 1,r,(pos << 1) + 2); } void insert(int l,int r,int v,int pos) { if(a[pos].l == l && a[pos].r == r) { a[pos].v = v; return ; } int mid = (a[pos].l + a[pos].r) >> 1; if(l > mid) insert(l,r,v,(pos << 1) + 2); else if(r <= mid) insert(l,r,v,(pos << 1) + 1); else { insert(l,mid,v,(pos << 1) + 1); insert(mid + 1,r,v,(pos << 1) + 2); } if(a[pos].v) { if(r < a[pos].r) { if(r >= mid) insert(r + 1,a[pos].r,a[pos].v,(pos << 1) + 2); else { insert(r + 1,mid,a[pos].v,(pos << 1) + 1); insert(mid + 1,a[pos].r,a[pos].v,(pos << 1) + 2); } } if(l > a[pos].l) { if(l <= mid + 1) insert(a[pos].l,l-1,a[pos].v,(pos << 1) + 1); else { insert(a[pos].l,mid,a[pos].v,(pos << 1) + 1); insert(mid + 1,l-1,a[pos].v,(pos << 1) + 2); } } } a[pos].v = 0; } int find(int p,int pos) { if(a[pos].v) return a[pos].v; if(a[pos].r == a[pos].l) return a[pos].v?a[pos].v:1; int mid = (a[pos].l + a[pos].r) >> 1; if(p <= mid) return find(p,(pos << 1) + 1); else return find(p,(pos << 1) + 2); } int main() { int T,l,r,q,v; scanf("%d",&T); for(int icase = 1;icase <= T;++icase) { scanf("%d%d",&n,&q); build(1,n,0); while(q--) { scanf("%d%d%d",&l,&r,&v); insert(l,r,v,0); } int ans = 0; for(int i = 1;i <= n;++i) ans += find(i,0); printf("Case %d: The total value of the hook is %d.\n",icase,ans); } return 0; }
相关文章推荐
- Linux安装memcached
- 第一个iOS程序–nib、xib与故事板的关系
- 链表的一点总结
- Android详细的对话框AlertDialog.Builder使用方法
- Android开发之WebService介绍
- Zabbix监控之Zabbix proxy
- css中ul li的背景小图标属性设置的两种情况
- Oracle分区表,哈希分区的新建与增加
- oracle数据查找方式以及索引的分类和索引失效的情况-------帮助了解索引从而优化我们oracle数据库
- 用Cacti来监控bind9的DNS解析情况
- yii中常用路径<转>
- ArcGIS 通视分析工作原理
- Gallery实现每次只滚动一张图片
- 2013 ACM/ICPC 长沙网络赛 J Candies (ZOJ)
- iOS培训教程——Photo应用解释
- U盘装系统中bios怎么设置USB启动(图文教程)
- 基于Cocos2d的MMORPG开发经验
- HTTP GET请求URL中IP被异常替换的问题
- 毫秒必争,前端网页性能最佳实践
- English,The Da Vinci Code, Chapter 26