洛谷 P1503 鬼子进村

题目背景

小卡正在新家的客厅中看电视。电视里正在播放放了千八百次依旧重播的《亮剑》,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战。

题目描述

描述 县城里有n个用地道相连的房子,第i个只与第i-1和第i+1个相连。这是有m个消息依次传来

1、消息为D x:鬼子将x号房子摧毁了,地道被堵上。

2、消息为R :村民们将鬼子上一个摧毁的房子修复了。

3、消息为Q x:有一名士兵被围堵在x号房子中。

李云龙收到信息很紧张,他想知道每一个被围堵的士兵能够到达的房子有几个。

输入输出格式

输入格式:

第一行2个整数n,m(n,m<=50000)。

接下来m行,有如题目所说的三种信息共m条。

输出格式:

对于每一个被围堵的士兵,输出该士兵能够到达的房子数。

输入输出样例

输入样例#1:

7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4

输出样例#1: ·

1
0
2
4

说明

若士兵被围堵在摧毁了的房子中,那只能等死了。。。。。。

思路:对于第一种操作,我们可以开一个vis数组记录某个地洞是否被堵了,同时要把堵了的地洞加入一个栈,为后面的第二种操作做准备,第二种操作,直接就把栈顶元素弹出来就好了,再把相应的vis数组清空,但是,第三种操作,貌似有些棘手,但是,我们仔细想一下,被困队员能到达的地洞可以认为是一个线性的数列,也就是说,是有左右边界的,而左右边界又正好是这个被困队员所在的被堵洞口的前驱和后继!用splay来维护一下就可以解决了!

代码:

#include<cstdio>
#include<cctype>
#include<stack>
#define maxn 50007
using namespace std;
int n,m,root,tot;
char c[2];
inline int qread() {
  char c=getchar();int num=0,f=1;
  for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  for(;isdigit(c);c=getchar()) num=num*10+c-'0';
  return num*f;
}
bool vis[maxn];
struct Tree {
  int fa,ch[2],val;
}t[maxn];
inline void rotate(int x) {
  int y=t[x].fa,z=t[y].fa;
  int k=t[y].ch[1]==x;
  t[z].ch[t[z].ch[1]==y]=x;
  t[x].fa=z;
  t[y].ch[k]=t[x].ch[k^1];
  t[t[x].ch[k^1]].fa=y;
  t[x].ch[k^1]=y,t[y].fa=x;
}
inline void splay(int x, int rt) {
  while(t[x].fa!=rt) {
    int y=t[x].fa,z=t[y].fa;
    if(z!=rt) (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
    rotate(x);
  }
  if(!rt) root=x;
}
inline void insert(int x) {
  int u=root,f=0;
  while(u&&t[u].val!=x) {
    f=u;
    u=t[u].ch[x>t[u].val];
  }
  if(u);
  else {
    u=++tot;
    if(f) t[f].ch[x>t[f].val]=u;
    t[u].fa=f,t[u].val=x;
  }
  splay(u,0);
}
inline void find(int x) {
  int u=root;
  if(!u) return;
  while(t[u].ch[x>t[u].val]&&x!=t[u].val) u=t[u].ch[x>t[u].val];
  splay(u,0);
}
inline int nxt(int x, int f) {
  find(x);
  int u=root;
  if(t[u].val>x&&f) return u;
  if(t[u].val<x&&!f) return u;
  u=t[u].ch[f];
  while(t[u].ch[f^1]) u=t[u].ch[f^1];
  return u;
}
inline void sc(int x) {
  int last=nxt(x,0),next=nxt(x,1);
  splay(last,0),splay(next,last);
  t[next].ch[0]=0;
}
stack<int>q;
int main() {
  n=qread(),m=qread();
  insert(0),insert(n+1);
  for(int i=1,x;i<=m;++i) {
    scanf("%s",c);
    if(c[0]=='D') {
      x=qread(),vis[x]=1;
      q.push(x),insert(x);  
    }
    if(c[0]=='R') {
      vis[q.top()]=0;
      sc(q.top());
      q.pop();
    }
    if(c[0]=='Q') {
      x=qread();
      if(vis[x]) printf("0\n");
      else printf("%d\n",t[nxt(x,1)].val-t[nxt(x,0)].val-1);
    }
  }
  return 0;
}
全部评论

相关推荐

行云流水1971:这份实习简历的优化建议: 结构清晰化:拆分 “校园经历”“实习经历” 板块(当前内容混杂),按 “实习→校园→技能” 逻辑排版,求职意向明确为具体岗位(如 “市场 / 运营实习生”)。 经历具象化:现有描述偏流程,需补充 “动作 + 数据”,比如校园活动 “负责宣传” 可加 “运营公众号发布 5 篇推文,阅读量超 2000+,带动 300 + 人参与”;实习内容补充 “协助完成 XX 任务,效率提升 X%”。 岗位匹配度:锚定目标岗位能力,比如申请运营岗,突出 “内容编辑、活动执行” 相关动作;申请市场岗,强化 “资源对接、数据统计” 细节。 信息精简:删减冗余表述(如重复的 “负责”),用短句分点,比如 “策划校园招聘会:联系 10 + 企业,组织 200 + 学生参与,到场率达 85%”。 技能落地:将 “Office、PS” 绑定经历,比如 “用 Excel 整理活动数据,输出 3 份分析表;用 PS 设计 2 张活动海报”,避免技能单独罗列。 优化后需强化 “经历 - 能力 - 岗位需求” 的关联,让实习 / 校园经历的价值更直观。 若需要进一步优化服务,私信
实习,投递多份简历没人回...
点赞 评论 收藏
分享
2025-12-28 20:47
已编辑
北京工商大学 Java
程序员牛肉:我靠你这个实习经历其实最需要担心的点是你做的太多了,可能会被面试官怀疑是你伪造的。 交易状态机是你做的,支付多渠道是你做的,对账是你做的,结算还是你做的,重复支付也是你做的,整个服务的异常处理也是你做的。 其实你这个反而问题很大的,你想想站在面试官的角度,他是真的会相信你的能力很强,还是相信这份实习你伪造了大部分?我相信你真的做了这么多,但是删一些,废话删一删。你这个做的太多了反而真实性不可信。 后面再补一个项目,在github上找一个高star的项目学一学然后写到自己简历上。我觉得你能力肯定没问题。28届能做到这个份上很厉害,但是在求职市场中,你不是在跟28届的同学比,把你这个简历放到27届其实也就一般水平。 所以后续要想一想看看能不能给自己简历上搞点亮点,比如开源贡献呢?比如博客呢?
实习要如何选择和准备?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务