poj(2892)——Tunnel Warfare(成段更新,寻找空间)
来源:互联网 发布:cda数据分析研究院 编辑:程序博客网 时间:2024/05/14 04:33
题目大意是:
给你n个房子,然后有m个操作:
(1):D x:代表摧毁第x个村庄
(2):Q x:查询与第x个村庄直接或间接(即为通过其他没有被炸毁的村庄相连接的)的村子的个数
(3):R :代表的是最后被摧毁的那个村庄被修复(这里就要用到栈了,哈哈)
唔。。。这道线段树的题目想了很久也没啥思路,网上说和poj hotel的那题很像,但是一直联系不起来,但是想通了也就这样吧。
其实线段树是一个很灵活的东西,它是辅助功能,这里它的作用是为了query(查询操作)与update(更新操作)。
当然其中还有一个lazy-tag的思想,那就是向上更新的时候,这个是经典的区间合并的操作,(其实我觉得叫这名字有点怪怪的感觉。。。
void pushup(int v){int temp=v<<1;tree[v].ls=tree[temp].ls;tree[v].rs=tree[temp+1].rs;if(tree[v].ls==tree[temp].r-tree[temp].l+1) tree[v].ls+=tree[temp+1].ls;if(tree[v].rs==tree[temp+1].r-tree[temp+1].l+1) tree[v].rs+=tree[temp].rs;tree[v].ms=max(tree[temp].rs+tree[temp+1].ls,max(tree[temp].ms,tree[temp+1].ms));}
首先讲讲更新操作,这里我们是把它更新到子节点,然后利用lazy思想在往上更新。
void update(int pos,int v,int cnt){if(tree[v].l==tree[v].r&&tree[v].l==pos){if(cnt==0) tree[v].ls=tree[v].rs=tree[v].ms=0;else tree[v].ls=tree[v].rs=tree[v].ms=1;return;}int mid=(tree[v].l+tree[v].r)>>1;int temp=v<<1;if(pos<=mid) update(pos,temp,cnt);else update(pos,temp+1,cnt);pushup(v);}
最重要的要数查找了吧(query)。
首先我们知道如果一个节点如果它满足当前节点是满的或是它是全空的,或是它是子节点,那么我们就返回当前节点的ms值(代表的是这个区间中的最大连续区间个数),如果不是,我们要分两种情况:
(1)首先当前节点是在左儿子的地方,如果pos这个我们要求的点是在左儿子的右区间内的话,那么我们还要再去判断一下是不是在右儿子上也有一段区间与左儿子相连,这也就是为什么要query(pos,temp)+query(pos,temp+1),后面的那个的目的就是为了查询判断一下在右儿子中是否还有一段连续的区间使得也刚好与左儿子相连 。
(2)讨论当前节点是在右儿子的地方,思路也是同样的。
如图中画黄线的所示:如果我们要查询2,那么我们还要判断右儿子上还有没有连起来的区间。
int query(int pos,int v){if(tree[v].ms==0||tree[v].ms==tree[v].r-tree[v].l+1||tree[v].l==tree[v].r){return tree[v].ms;}int temp=v<<1;int mid=(tree[v].l+tree[v].r)>>1;if(pos<=mid){if(pos>=tree[temp].r-tree[temp].rs+1) return query(pos,temp)+query(mid+1,temp+1);else return query(pos,temp);}else{if(pos<=tree[temp+1].l+tree[temp+1].ls-1) return query(mid,temp)+query(pos,temp+1);else return query(pos,temp+1);}}
总之挺不错的一道线段树的题目,一开始我一直不知道要怎么把线段树给用上去。。。
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<stack>using namespace std;stack<int> sk;#define maxn 55555struct node{int l,r;int ls,rs,ms;}tree[maxn*4];void pushup(int v){int temp=v<<1;tree[v].ls=tree[temp].ls;tree[v].rs=tree[temp+1].rs;if(tree[v].ls==tree[temp].r-tree[temp].l+1) tree[v].ls+=tree[temp+1].ls;if(tree[v].rs==tree[temp+1].r-tree[temp+1].l+1) tree[v].rs+=tree[temp].rs;tree[v].ms=max(tree[temp].rs+tree[temp+1].ls,max(tree[temp].ms,tree[temp+1].ms));}void build(int l,int r,int v){tree[v].l=l;tree[v].r=r;tree[v].ls=tree[v].rs=tree[v].ms=r-l+1;if(l==r) return;int mid=(l+r)>>1;int temp=v<<1;build(l,mid,temp);build(mid+1,r,temp+1);}int query(int pos,int v){if(tree[v].ms==0||tree[v].ms==tree[v].r-tree[v].l+1||tree[v].l==tree[v].r){return tree[v].ms;}int temp=v<<1;int mid=(tree[v].l+tree[v].r)>>1;if(pos<=mid){if(pos>=tree[temp].r-tree[temp].rs+1) return query(pos,temp)+query(mid+1,temp+1);else return query(pos,temp);}else{if(pos<=tree[temp+1].l+tree[temp+1].ls-1) return query(mid,temp)+query(pos,temp+1);else return query(pos,temp+1);}}void update(int pos,int v,int cnt){if(tree[v].l==tree[v].r&&tree[v].l==pos){if(cnt==0) tree[v].ls=tree[v].rs=tree[v].ms=0;else tree[v].ls=tree[v].rs=tree[v].ms=1;return;}int mid=(tree[v].l+tree[v].r)>>1;int temp=v<<1;if(pos<=mid) update(pos,temp,cnt);else update(pos,temp+1,cnt);pushup(v);}int main(){int n,m;scanf("%d%d",&n,&m);build(1,n,1);while(!sk.empty()){sk.pop();}char a[5];int x;while(m--){scanf("%s",a);if(a[0]=='D'){scanf("%d",&x);sk.push(x);update(x,1,0);}else if(a[0]=='Q'){scanf("%d",&x);printf("%d\n",query(x,1));}else{x=sk.top();sk.pop();update(x,1,1);}}}
加油,wish everyone can achieve their dream!【Acmer ,fighting~ ∶)
0 0
- poj(2892)——Tunnel Warfare(成段更新,寻找空间)
- poj 2892 Tunnel Warfare
- poj 2892 Tunnel Warfare
- poj 2892 Tunnel Warfare
- poj 2892 Tunnel Warfare
- POJ 2892 Tunnel Warfare
- poj 2892 Tunnel Warfare
- POJ 2892 Tunnel Warfare
- POJ 2892 Tunnel Warfare
- poj 2892Tunnel Warfare
- POJ-2892 Tunnel Warfare
- Poj 2892 Tunnel Warfare
- POJ 2892 Tunnel Warfare
- POJ 2892 Tunnel Warfare
- POJ 2892 Tunnel Warfare
- poj 2892 Tunnel Warfare
- poj 2892 Tunnel Warfare(线段树)
- POJ 2892 Tunnel Warfare (线段树)
- Struts2 XML配置详解
- iOS_ScrollView的自动布局
- 【分析总结框架记录】boost使用
- Android ble 蓝牙4.0 总结
- dsa算法(26)
- poj(2892)——Tunnel Warfare(成段更新,寻找空间)
- 使用python对shapefile重投影
- 浅析 hyper -- 新一代虚拟机技术?
- Linux内核与驱动开发学习总结:内核初始化宏__init(十二)
- myeclipse 控制台 中文乱码
- Android中通知的使用-----Notification详解
- c++读书笔记之表达式
- MySQL学习系列7:插入insert 更新update 删除delete
- UML总结复习指南