HDU 1540 Tunnel Warfare
2015-09-01 00:08
465 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540
题意:有n个相邻的村子,D操作将该村子与左右的连接切断,R操作是将上次切断的道路恢复,Q操作是询问包括x在内的连续的村子
思路:线段树区间合并,和hotel不一样的是这题是单点更新,更新大同小异,因为是单点更新所以没用lazy标志,询问的时候比较不一样,判断改点是否在横跨左右子数的区间内,是则直接输出答案,否则继续向子树查询
题意:有n个相邻的村子,D操作将该村子与左右的连接切断,R操作是将上次切断的道路恢复,Q操作是询问包括x在内的连续的村子
思路:线段树区间合并,和hotel不一样的是这题是单点更新,更新大同小异,因为是单点更新所以没用lazy标志,询问的时候比较不一样,判断改点是否在横跨左右子数的区间内,是则直接输出答案,否则继续向子树查询
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <stack> #define maxn 50030 using namespace std; struct Tree { int l,r; int lsum,rsum; }tree[maxn*3]; stack <int> s; void Pushup(int root) { int ll=tree[root<<1].r-tree[root<<1].l+1; tree[root].lsum=tree[root<<1].lsum; if (tree[root].lsum==ll) tree[root].lsum+=tree[root<<1|1].lsum; //cout<<":"<<root<<endl; int rr=tree[root<<1|1].r-tree[root<<1|1].l+1; tree[root].rsum=tree[root<<1|1].rsum; if (tree[root].rsum==rr) tree[root].rsum+=tree[root<<1].rsum; } void build(int root,int l,int r) { tree[root].l=l; tree[root].r=r; tree[root].lsum=r-l+1; tree[root].rsum=r-l+1; if (l==r) return; int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); Pushup(root); } void update(int root,int gold,int val) { //cout<<":"<<root<<endl; if (tree[root].l==tree[root].r) { if (val==0) tree[root].lsum=tree[root].rsum=0; else tree[root].lsum=tree[root].rsum=1; return; } int mid=(tree[root].l+tree[root].r)>>1; if (gold<=mid) update(root<<1,gold,val); else if (gold>mid) update(root<<1|1,gold,val); Pushup(root); // cout<<":"<<root<<endl; } int que(int root,int gold) { if (tree[root].l==tree[root].r ) return tree[root].lsum; int mid=(tree[root].l+tree[root].r)>>1; int ll=mid-tree[root<<1].rsum+1; int rr=mid+tree[root<<1|1].lsum;//cout<<ll<<":"<<rr<<endl; if (gold>=ll && gold <=rr) return tree[root<<1].rsum+tree[root<<1|1].lsum; else if (gold<ll) return que(root<<1,gold); else if (gold>rr) return que(root<<1|1,gold); } int main() { int n,m; while (scanf("%d%d",&n,&m)!=EOF) { //while (s.size()) s.pop(); build(1,1,n); for (int i=0;i<m;i++) { char tem; cin>>tem; if (tem=='D') { int a; scanf("%d",&a); update(1,a,0); s.push(a); } else if (tem=='R') { int a=s.top(); s.pop(); update(1,a,1); } else if (tem=='Q') { int a; scanf("%d",&a); printf("%d\n",que(1,a)); } } } }
相关文章推荐
- PHP中利用pcntl进行多进程并发控制
- 公司内部培训AlwaysOn PPT分享
- 笔试题:乱序求第n大(小)的数。我能想到的最好的方法。
- zTree节点上右击弹出菜单进行增删改操作---jquery.popupSmallMenu
- 使用Qt Style Sheets制作UI特效
- 十一、MDT 2013 Update 1批量部署-SERVER 2012 R2 标准版的安装
- 转:一个合格的程序员应该读过哪些书
- netstat详解
- 解析Qt自带的Style示例
- Qt的皮肤设计(Style Sheet)
- jsp
- crazyflie2终于可以连接到PC client -- 记录下之前遇到的困难和解决方法
- Android Api Demos登顶之路(五十四)Service LocalService Binding
- 职业打假人,这几年的沉浮路
- JQuery自适应窗口大小导航菜单附源码下载
- js+CSS实现模拟华丽的select控件下拉菜单效果
- jquery常用函数与方法汇总
- jQuery中常用的遍历函数用法实例总结
- JS实现的自定义右键菜单实例二则
- JavaScript中this详解