P1503 鬼子进村
2022/9/10 23:27:29
本文主要是介绍P1503 鬼子进村,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
题面
县城里有 \(n\) 个用地道相连的房子,初始时全部房屋未被摧毁,第 \(i\) 个只与第 \(i-1\) 和第 \(i+1\) 个相连。这时有 \(m\) 个消息依次传来:
-
若消息为
D x
:鬼子将 \(x\) 号房子摧毁了,地道被堵上。 -
若消息为
R
:村民们将鬼子上一个摧毁的房子修复了。 -
若消息为
Q x
:有一名士兵被围堵在 \(x\) 号房子中。
李云龙收到信息很紧张,他想知道每一个被围堵的士兵通过地道能够到达的房子有几个。请注意,如果士兵所在的房子已被摧毁,那么他无法行动。
\(1\leq n,m\leq 5\times 10^4\)。
思路
这道题我先想到了一个 std::set
做法,但是不想写二分,于是想到了一个正经的平衡树做法。
首先,我们用一个栈和一个平衡树来维护被摧毁的元素,然后用一个状态数组维护房屋是否被摧毁。
- 如果是一个摧毁操作,那么将 \(x\) 放入栈、平衡树中。然后标记。
- 如果是一个修复操作,那么将栈顶元素从平衡树中删除,并取消标记,然后出栈。
- 如果是要给询问操作,可见这就是在询问平衡树中 \(x\) 的前驱后继的距离(也就是到被破坏的距离)减 \(2\)(首尾被破坏)。直接在平衡树上处理即可。
注意,可能当前没有房屋被破坏,直接询问会出锅,我们可以插入虚拟节点 \(0,n+1\),由于它们不存在,把它们看成摧毁了的房屋是可以的。
平衡树这里使用的我最近学习的 \(\textbf{FHQ Treap}\)。
时间复杂度 \(O(m\log n)\)。
代码
#include <bits/stdc++.h> #define int long long using namespace std; namespace FHQTreap{ const int SIZE = 5e4+5; int son[SIZE][2]; int val[SIZE],rk[SIZE],siz[SIZE],root,points; mt19937 randomer(time(0)); #define ls(i) (son[(i)][0]) #define rs(i) (son[(i)][1]) void pushup(int i){ siz[i]=siz[ls(i)]+siz[rs(i)]+1; } int newnode(int v){ val[++points]=v; rk[points]=randomer(); siz[points]=1; return points; } void split(int p,int v,int &left,int &right){ if(!p){ left=right=0; return; } if(val[p]<=v){ left=p; split(rs(p),v,rs(left),right); } else{ right=p; split(ls(p),v,left,ls(right)); } pushup(p); } int merge(int left,int right){ if(!left||!right){ if(left)return left; else if(right)return right; else return 0; } if(rk[left]<rk[right]){ ls(right)=merge(left,ls(right)); pushup(right); return right; } else{ rs(left)=merge(rs(left),right); pushup(left); return left; } } void insert(int v){ int left=0,right=0; split(root,v-1,left,right); root=merge(merge(left,newnode(v)),right); } void remove(int v){ int left=0,mid=0,right=0; split(root,v,left,right); split(left,v-1,left,mid); mid=merge(ls(mid),rs(mid)); root=merge(merge(left,mid),right); } int pre(int v){ int now=root,ret=0; while(1){ if(!now){ return ret; } else if(v<=val[now]){ now=ls(now); } else{ ret=val[now]; now=rs(now); } } } int next(int v){ int now=root,ret=0; while(1){ if(!now){ return ret; } else if(v>=val[now]){ now=rs(now); } else{ ret=val[now]; now=ls(now); } } } } namespace solution{ int n,m; stack<int> destoried; bool status[50005]; int solution(){ cin>>n>>m; FHQTreap::insert(0); FHQTreap::insert(n+1); while(m--){ char op;int x; cin>>op; if(op=='D'){ cin>>x; destoried.push(x); FHQTreap::insert(x); status[x]=true; } else if(op=='R'){ FHQTreap::remove(destoried.top()); status[destoried.top()]=false; destoried.pop(); } else{ cin>>x; if(status[x]){ cout<<0<<'\n'; } else{ cout<<(FHQTreap::next(x)-FHQTreap::pre(x)-1)<<'\n'; } } } return 0; } } signed main(){ ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr); return solution::solution(); }
AC Record
这篇关于P1503 鬼子进村的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-01为什么公共事业机构会偏爱 TiDB :TiDB 数据库在某省妇幼健康管理系统的应用
- 2024-04-26敏捷开发:想要快速交付就必须舍弃产品质量?
- 2024-04-26静态代码分析的这些好处,我竟然都不知道?
- 2024-04-26你在测试金字塔的哪一层?(下)
- 2024-04-26快刀斩乱麻,DevOps让代码评审也自动起来
- 2024-04-262024年最好用的10款ER图神器!
- 2024-04-2203-为啥大模型LLM还没能完全替代你?
- 2024-04-2101-大语言模型发展
- 2024-04-17基于SpringWeb MultipartFile文件上传、下载功能
- 2024-04-14个人开发者,Spring Boot 项目如何部署