平衡二叉树SBT||线段树区间维护poj2892
来源:互联网 发布:朗伽病理软件 编辑:程序博客网 时间:2024/05/11 18:36
题意:有第三种操作:
D x表示毁掉村庄x;
Q x表示询问x在内的最大连续的村庄;
R表示重建最近被毁掉的村庄
思路:用一个栈存储被毁掉的村庄,以便修复。开一个访问数组,如果村庄被毁掉则标记,查询的时候直接输出0;
然后线段树维护连续的村庄。
#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=50010;int n,m;bool vis[maxn];stack<int> s;struct IntervalTree{ int ls[maxn<<3],rs[maxn<<3]; void maintain(int o,int l,int r) { ls[o]=ls[o<<1],rs[o]=rs[o<<1|1]; int mid=(l+r)>>1; if(ls[o]==mid-l+1)ls[o]+=ls[o<<1|1]; if(rs[o]==r-mid)rs[o]+=rs[o<<1]; } void build(int o,int l,int r) { ls[o]=rs[o]=0; if(l==r) { ls[o]=rs[o]=1; return; } int mid=(l+r)>>1; build(o<<1,l,mid); build(o<<1|1,mid+1,r); maintain(o,l,r); } void update(int o,int l,int r,int pos,int x) { if(l==r) { ls[o]+=x; rs[o]+=x; return ; } int mid=(l+r)>>1; if(pos<=mid)update(o<<1,l,mid,pos,x); else update(o<<1|1,mid+1,r,pos,x); maintain(o,l,r); } int query(int o,int l,int r,int pos)//注意一下如何查询 { int ans=0; if(l==r)return 1; int mid=(l+r)>>1; if(pos<=mid) { if(pos>=mid-rs[o<<1]+1)return query(o<<1,l,mid,pos)+ls[o<<1|1];//如果在连续的那一段则要加上右孩子右面连续的一段; else return query(o<<1,l,mid,pos); } else { if(pos<=mid+ls[o<<1|1])return query(o<<1|1,mid+1,r,pos)+rs[o<<1]; return query(o<<1|1,mid+1,r,pos); } }}tree;int main(){ //freopen("in.txt","r",stdin); char op[5]; int x; scanf("%d%d",&n,&m); tree.build(1,1,n); memset(vis,0,sizeof(vis)); while(m--) { scanf("%s",op); if(op[0]=='D') { scanf("%d",&x); vis[x]=1; tree.update(1,1,n,x,-1); s.push(x); } else if(op[0]=='Q') { scanf("%d",&x); if(vis[x])printf("0\n"); else printf("%d\n",tree.query(1,1,n,x)); } else { x=s.top();s.pop(); vis[x]=0; tree.update(1,1,n,x,1); } } return 0;}
现在用SBT重写一遍。
树中保存已经被摧毁的村庄,查询的时候只需要找到x的前驱跟后继,相减再减一就是区间长度
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=50010;int vis[maxn];int N,M;stack<int> st;int root,tot;void init(){ while(!st.empty())st.pop(); memset(vis,0,sizeof(vis)); root=tot=0;}struct SBT{ int left,right,size,key; void init(int val) { left=right=0; key=val; size=1; }}tree[maxn];void left_rotate(int &x){ int y=tree[x].right; tree[x].right=tree[y].left; tree[y].left=x; tree[y].size=tree[x].size; tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; x=y;}void right_rotate(int &x){ int y=tree[x].left; tree[x].left=tree[y].right; tree[y].right=x; tree[y].size=tree[x].size; tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; x=y;}void maintain(int &x,int flag){ if(!flag) { if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size) right_rotate(x); else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size) left_rotate(tree[x].left),right_rotate(x); else return; } else { if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size) left_rotate(x); else if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size) right_rotate(tree[x].right),left_rotate(x); else return; } maintain(tree[x].left,0); maintain(tree[x].right,1); maintain(x,0); maintain(x,1);}//插入值为key的节点void insert(int &x,int key){ if(!x) { x=++tot; tree[x].init(key); } else { tree[x].size++; if(key<tree[x].key)insert(tree[x].left,key); else insert(tree[x].right,key); maintain(x,key>=tree[x].key); }}int del(int &x,int key){ if(!x)return 0; tree[x].size--; if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)|| (key>tree[x].key&&tree[x].right==0)) { if(tree[x].left&&tree[x].right) { int p=del(tree[x].left,key+1); tree[x].key=tree[p].key; return p; } else { int p=x; x=tree[x].left+tree[x].right; return p; } } else return del(key<tree[x].key?tree[x].left:tree[x].right,key);}//返回值v的前驱的值,如果没有前驱返回v本身int Pred(int t,int v){ if(!t)return v; if(v<=tree[t].key)return Pred(tree[t].left,v); else { int tmp=Pred(tree[t].right,v); return v==tmp?tree[t].key:tmp; }}//返回值v的后继的值,如果没有后继返回v本身int Succ(int t,int v){ if(!t)return v; if(v>=tree[t].key)return Succ(tree[t].right,v); else { int tmp=Succ(tree[t].left,v); return v==tmp?tree[t].key:tmp; }}int main(){ char op[5]; int x; while(scanf("%d%d",&N,&M)!=EOF) { init(); while(M--) { scanf("%s",op); if(op[0]=='D') { scanf("%d",&x); //if(vis[x])continue; vis[x]++; st.push(x); insert(root,x); } else if(op[0]=='R') { if(!st.empty()) { del(root,st.top()); vis[st.top()]--; if(vis[st.top()]<=0)st.pop(); } } else { scanf("%d",&x); if(vis[x])printf("0\n"); else { int r=Succ(root,x); if(r==x)r=N+1; int l=Pred(root,x); if(l==x)l=0; printf("%d\n",r-l-1); } } } } return 0;}
0 0
- 平衡二叉树SBT||线段树区间维护poj2892
- poj2892,线段树单点更新,区间合并
- hdu1540 poj2892 Tunnel Warfare 线段树端点更新 SBT
- SBT 平衡二叉树模板
- 平衡二叉树SBT模板
- SBT 平衡二叉树,POJ 3481
- C# 平衡二叉树 SBT 源码
- 【平衡二叉树】SBT学习笔记
- poj2892--Tunnel Warfare(线段树)
- 线段树处理 poj2892 hdu1540
- 线段树区间维护upcoj
- 线段树区间维护hdu3308
- 线段树区间维护hdu3397
- 线段树区间维护cf46D
- POJ3468 线段树区间维护
- POJ2892 Tunnel Warfare (平衡树)
- SBT平衡树
- 平衡树SBT模板
- HDOJ-1561(树形DP)
- Spring+Hibernate框架下MySql读写分离,主从数据库配置
- Jedis、JedisPool、Jedis分布式实例介绍
- 通过CMD来打开一个C#程序,并传入参数
- 两种方式建立Vsftpd虚拟用户
- 平衡二叉树SBT||线段树区间维护poj2892
- UIApplication详解
- 堆
- 1602时钟
- 求素数
- Javascript OOP Basics
- edward_mj退役经验帖(浙大2届Final队员陈伟杰的退役贴)
- 正则表达式匹配/
- linux之sort用法