hdu1540&poj2892Tunnel Warfare(线段树单点更新)
来源:互联网 发布:交通渠化与组织优化 编辑:程序博客网 时间:2024/06/15 05:33
->题目请戳这 和这->
题目大意,给n个点表示n个村庄,一开始都是相连的,现在有3种操作:Q x,查询第与第x个村庄相连的村庄个数;D x,摧毁掉第x个村庄;R 恢复刚摧毁的村庄。
题目分析:每个点用2个状态表示,0表示被摧毁,1表示存在,因为有恢复操作,并且每次恢复上一个被摧毁的村庄,所以用一个栈存储所有被摧毁的村庄,每次R操作恢复栈顶村庄。这题关键是查询操作,如果查询的村庄x不存在,则没有村庄与之相连通,如果存在x村庄,那么从x往2边找连续的存在的村庄。如何找这个连续的存在的村庄,这里提供2种方法:
1。自顶向下找,如果找到左边第一个不存在的村庄,找到右边第一个不存在的村庄,相减即可。
2。自底向上找,我们建立线段树的时候把每个叶子节点即每个村庄的位置找到,然后分别从x-1和x+1的位置往两边找,也是找到第一个不存在的村庄为止。
本来比较看好第二种方法,实际提交了一下,第一种效率貌似高一点。
详情请见代码:
自顶向下:
#include <iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 50005;int stack[N],top;int n,m;int tree[N<<2];char op[3];int leaf[N];void build(int num,int s,int e){ if(s == e) { tree[num] = 1; leaf[s] = num; return; } int mid = (s + e)>>1; build(num<<1,s,mid); build(num<<1|1,mid + 1,e); tree[num] = tree[num<<1] + tree[num<<1|1];}void insert(int num,int s,int e,int pos,int val){ if(s == e) { tree[num] = val; return; } int mid = (s + e)>>1; if(pos <= mid) insert(num<<1,s,mid,pos,val); else insert(num<<1|1,mid + 1,e,pos,val); if(tree[num<<1] == mid - s + 1 && tree[num<<1|1] == e - mid) tree[num] = e - s + 1; else tree[num] = 0;}int query(int num,int s,int e,int pos,int dir){ if(pos > n || pos < 1) return pos; if(tree[num] == e - s + 1) { if(dir)//-> return query(1,1,n,e + 1,dir);//重新从e+1开始往右找 else return query(1,1,n,s - 1,dir); } if(s == e) return s; int mid = (s + e)>>1; if(pos <= mid) return query(num<<1,s,mid,pos,dir); else return query(num<<1|1,mid + 1,e,pos,dir);}void print(int num,int s,int e){ for(int i = 1;i <= n;i ++) printf("%d ",tree[leaf[i]]);}int main(){ int x; int cnt; while(scanf("%d%d",&n,&m) != EOF) { build(1,1,n); top = 0; while(m --) { scanf("%s",op); if(op[0] == 'R') { insert(1,1,n,stack[--top],1); } else { scanf("%d",&x); if(op[0] == 'D') { insert(1,1,n,x,0); stack[top ++] = x; } else { int ans = tree[leaf[x]]; if(ans == 0) printf("0\n"); else { ans = 1; if(x < n) { cnt = query(1,1,n,x + 1,1);//右 ans += (cnt - x - 1); } //printf("cnt:%d\n",cnt); if(x > 1) { cnt = query(1,1,n,x - 1,0);//左 ans += (x - cnt - 1); } //printf("cnt:%d\n",cnt); printf("%d\n",ans); } } } } } return 0;}//hdu546MS1008K//poj1036K266MS自底向上找:
#include <iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 50005;int stack[N],top;int n,m;struct node{ int l,r,len;}tree[N<<2];char op[3];int leaf[N];void build(int num,int s,int e){ if(s == e) { tree[num].len = 1; tree[num].l = tree[num].r = s; leaf[s] = num; return; } int mid = (s + e)>>1; build(num<<1,s,mid); build(num<<1|1,mid + 1,e); tree[num].len = tree[num<<1].len + tree[num<<1|1].len; tree[num].l = s; tree[num].r = e;}void insert(int num,int pos,int val){ if(tree[num].l == tree[num].r) { tree[num].len = val; return; } int mid = (tree[num].l + tree[num].r)>>1; if(pos <= mid) insert(num<<1,pos,val); else insert(num<<1|1,pos,val); if(tree[num<<1].len == mid - tree[num].l + 1 && tree[num<<1|1].len == tree[num].r - mid) tree[num].len = tree[num].r - tree[num].l + 1; else tree[num].len = 0;}void print(){ int i; for(i = 1;i <= n;i ++) printf("%d ",tree[leaf[i]].len); putchar(10);}int main(){ int x; int cnt; while(scanf("%d%d",&n,&m) != EOF) { build(1,1,n); top = 0; while(m --) { scanf("%s",op); if(op[0] == 'R') { insert(1,stack[--top],1); } else { scanf("%d",&x); if(op[0] == 'D') { insert(1,x,0); stack[top ++] = x; } else { int ans = tree[leaf[x]].len; if(ans == 0) printf("0\n"); else { int tl,tr; tl = x - 1;//记录x左边第一个断点 tr = x + 1;//记录x右边第一个断点 int tmp; while(tl >= 1 && tree[leaf[tl]].len == 1) { tmp = leaf[tl]; if(tmp & 1)//在右子树上,往根找就是往左找 { while(tree[tmp].len == tree[tmp].r - tree[tmp].l + 1 && tmp > 1) { tmp /= 2; if(!(tmp & 1))//到了左子树上,找到头了 { break; } } if(tree[tmp].len == tree[tmp].r - tree[tmp].l + 1)//加上这句优化后hdu515MS2032K tl = tree[tmp].l - 1;//poj2068K282MS else tl = tree[tmp<<1|1].l - 1; } else tl --; } while(tr <= n && tree[leaf[tr]].len == 1) { tmp = leaf[tr]; if(tmp & 1) tr ++; else { while(tree[tmp].len == tree[tmp].r - tree[tmp].l + 1 && tmp > 1) { tmp /= 2; if(tmp & 1)//找到了右子树上面,找到最右边了 break; } if(tree[tmp].len == tree[tmp].r - tree[tmp].l + 1) tr = tree[tmp].r + 1; else tr = tree[tmp<<1].r + 1; } } //printf("tl:%d tr:%d\n",tl,tr); ans = tr - tl - 1; printf("%d\n",ans); } } } //print(1,1,n); //putchar(10); } } return 0;}//hdu1031MS2032K//poj2068K391MS
- hdu1540&poj2892Tunnel Warfare(线段树单点更新)
- hdu1540 poj2892 Tunnel Warfare 线段树端点更新 SBT
- hdu1540Tunnel Warfare (线段树,单点更新)
- hdu1540 Tunnel Warfare 线段树中等难题
- HDU1540:Tunnel Warfare(线段树区间合并)
- hdu1540 Tunnel Warfare 线段树区间合并
- poj2892 同hdu1540 Tunnel Warfare 线段树
- HDU1540-Tunnel Warfare-线段树区间合并
- hdu1540 Tunnel Warfare(线段树)
- HDU1540 Tunnel Warfare(线段树+set)
- hdu1540 Tunnel Warfare 线段树区间合并
- HDU1540 Tunnel Warfare (线段树区间合并)
- poj2892&&HDU1540 Tunnel Warfare(线段树)
- hdu1540-Tunnel Warfare 线段树区间合并
- HDU1540 Tunnel Warfare(线段树,区间合并)
- HDU1540 Tunnel Warfare (线段树区间合并)
- HDU1540 Tunnel Warfare(线段树+区间合并)
- HDU1540 Tunnel Warfare(线段树区间合并)
- unity做一个血条
- HIERARCHICAL QUERIES AND SYS_CONNECT_BY_PATH
- Windows运行命令大全
- java中Map集合遍历方法
- WAF与IPS的区别与各自的详细介绍
- hdu1540&poj2892Tunnel Warfare(线段树单点更新)
- Oracle 中 DELETE 与 TRUNCATE 语句的区别及优缺点
- SurfaceFlinger Layer Clip and Draw---大密度注释
- 帮助软件开发者提高效率的10个小窍门
- NOIP1999 拦截导弹
- android 应用级别 亮度调节
- HttpClient4.0
- MySQL控制台倒入本地txt文件到远程数据库中
- 运算符重载——重载+和-对复数类对象进行加减运算