poj2892 Tunnel Warfare

题面在这里
题目大意:
n 个物品排成一行。三种操作:

  • D x 表示将第x个物品摧毁;

    • R 表示将上一个物品回复;
    • Q x 表示查询x所在连通块的个数。
    • 做法:
      平衡树中保存摧毁的物品编号。
      查询时只需查询 x 的前驱pre后继 nxt ,然后输出 nxtpre1 即可。

      /*************************************************************
          Problem: poj 2892 Tunnel Warfare
          User: fengyuan
          Language: C++
          Result: Accepted
          Time: 266 ms
          Memory: 1.1 MB
          Submit_Time: 2017-12-09 00:12:45
      *************************************************************/
      
      #include<cstdio>
      #include<cstring>
      #define rep(i, x, y) for (int i = (x); i <= (y); i ++)
      #define down(i, x, y) for (int i = (x); i >= (y); i --)
      #define mid ((l+r)/2)
      #define lc (o<<1)
      #define rc (o<<1|1)
      #define pb push_back
      #define mp make_pair
      #define PII pair<int, int>
      #define F first
      #define S second
      #define B begin()
      #define E end()
      using namespace std;
      typedef long long LL;
      //head
      
      const int N = 50010, M = 1500010;
      int n, m, top, rt, tot;
      char opt[5];
      bool vis[N];
      int st[N];
      int fa[M], ch[M][2], data[M];
      
      inline void clear(int x)
      {
          fa[x] = ch[x][0] = ch[x][1] = data[x] = 0;
      }
      
      inline void rot(int x)
      {
          int y = fa[x], z = fa[y];
          int f = ch[y][1] == x;
          ch[y][f] = ch[x][f^1]; if (ch[x][f^1]) fa[ch[x][f^1]] = y;
          fa[x] = z; if (z) ch[z][ch[z][1] == y] = x;
          fa[y] = x; ch[x][f^1] = y;
      }
      
      inline void splay(int x, int top)
      {
          while (fa[x] != top){
              int y = fa[x], z = fa[y];
              if (z != top) rot(((ch[z][0] == y) == (ch[y][0] == x)) ? y : x);
              rot(x);
          }
          if (!top) rt = x;
      }
      
      inline int find(int v)
      {
          int x = rt;
          while (x){
              if (data[x] == v){ splay(x, 0); return x; }
              x = ch[x][v > data[x]];
          }
      }
      
      inline int pre(int x)
      {
          x = ch[x][0];
          while (ch[x][1]) x = ch[x][1];
          return x;
      }
      
      inline int nxt(int x)
      {
          x = ch[x][1];
          while (ch[x][0]) x = ch[x][0];
          return x;
      }
      
      inline void insert(int v)
      {
          int x = rt;
          if (!rt){
              rt = x = ++ tot;
              data[x] = v;
              fa[x] = ch[x][0] = ch[x][1] = 0;
              return;
          }
          while (x){
              int &y = ch[x][v > data[x]];
              if (!y){
                  y = ++ tot;
                  data[y] = v;
                  fa[y] = x; ch[y][0] = ch[y][1] = 0;
                  x = y; break;
              } x = y;
          } splay(x, 0);
      }
      
      inline void del(int v)
      {
          int x = find(v);
          if (!ch[x][0] && !ch[x][1]){ clear(x); rt = 0; return; }
          if (!ch[x][0]){ rt = ch[x][1]; fa[rt] = 0; return; }
          if (!ch[x][1]){ rt = ch[x][0]; fa[rt] = 0; return; }
          int p = pre(x), rtt = rt;
          splay(p, 0); ch[rt][1] = ch[rtt][1]; fa[ch[rtt][1]] = rt;
          clear(rtt);
      }
      
      int main()
      {
          scanf("%d%d", &n, &m);
          insert(0); insert(n+1);
          while (m --){
              scanf("%s", opt); int x;
              if (opt[0] == 'D'){
                  scanf("%d", &x);
                  vis[x] = 1; st[++ top] = x;
                  insert(x);
              } else if (opt[0] == 'R'){
                  del(st[top]);
                  vis[st[top --]] = 0;
              } else {
                  scanf("%d", &x);
                  if (vis[x]){ puts("0"); continue; }
                  insert(x);
                  printf("%d\n", data[nxt(rt)] - data[pre(rt)] - 1);
                  del(x);
              }
          }
          return 0;
      }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值