zoukankan      html  css  js  c++  java
  • 洛谷 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
    ");
    	  else printf("%d
    ",t[nxt(x,1)].val-t[nxt(x,0)].val-1);
    	}
      }
      return 0;
    }
    
  • 相关阅读:
    2015/12/26 十六、 八 、二 进制转十进制
    2015/12/25 ① 图灵测试 ② 安装jdk出现的问题 ③ 配置环境变量
    java如何产生随机数
    二分查找法
    冒泡排序法
    计算阶乘
    九九乘法小练习
    数组循环语句练习
    经典循环例题练习
    如何用循环语句输出一个三角形
  • 原文地址:https://www.cnblogs.com/grcyh/p/10569465.html
Copyright © 2011-2022 走看看