鬼子进村

传送门

这题什么玩意……提示说这是个平衡树题,不过一来我没看出这是平衡树,二来我早忘了怎么写平衡树了。

我想到的是用线段树解决。前两个摧毁和重建的操作都只需要进行单点修改,而第三个操作,我的想法就是找到这个点左边最靠右的一间被摧毁的屋子和右边最靠左的一间被摧毁的屋子。

我们把所有点的权值一开始设成1,之后鬼子摧毁一个就变成0。统计的时候计算一下如果一段的区间和=区间长度说明这段区间之内是没有0的,否则就有。我们递归访问就行。

然后我使用了传参的线段树……就出现了一些极致bug,比如建树的时候的记录编号的点,和访问的时候记录编号的点正好差了一倍……(????!)

后来经过无数debug无果还是使用动态开点记录的线段树。这样的话我们可以更精准的进行区间的访问,也就可以解决点数差一倍的麻烦……

看一下代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<set>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('
')

using namespace std;
typedef long long ll;
const int M = 50005;
const int INF = 1000000009;

int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
      if(ch == '-') op = -1;
      ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
  {
      ans *= 10;
      ans += ch - '0';
      ch = getchar();
    }
    return ans * op;
}

struct seg
{
    int l,r,v;
}t[M<<2];

bool pd[M];
int x,n,m,des[M],head,k1,k2;

void build(int p,int kl,int kr)
{
    t[p].l = kl,t[p].r = kr;
    if(kl == kr)
    {
      t[p].v = 1;
      return;
    }
    int mid = (kl + kr) >> 1;
    build(p<<1,kl,mid);
    build(p<<1|1,mid+1,kr);
    t[p].v = t[p<<1].v + t[p<<1|1].v;
}

void modify(int p,int pos,int val)
{
    if(t[p].l == pos && t[p].r == pos)
    {
      t[p].v = val;
      pd[pos] = val;
      return;
    }
    int mid = (t[p].l + t[p].r) >> 1;
    if(pos <= mid) modify(p<<1,pos,val);
    else modify(p<<1|1,pos,val);
    t[p].v = t[p<<1].v + t[p<<1|1].v;
}

int query(int p,int kl,int kr)
{
    if(t[p].l == kl && t[p].r == kr) return t[p].v;
    int mid = (t[p].l + t[p].r) >> 1;
    if(kr <= mid) return query(p<<1,kl,kr);
    else if(kl > mid) return query(p<<1|1,kl,kr);
    else return query(p<<1,kl,mid) + query(p<<1|1,mid+1,kr);
}

int search1(int p,int kl,int kr)
{
    if(t[p].l == kl && t[p].r == kr && kl == kr && t[p].v == 0) return kl;
    if(t[p].l == kl && t[p].r == kr && kl == kr && t[p].v == 1) return 0;
    int mid = (t[p].l + t[p].r) >> 1;
    if(kr <= mid) return search1(p<<1,kl,kr);
    else if(kl > mid) return search1(p<<1|1,kl,kr);
    else
    {
      int d = query(p,t[p<<1|1].l,kr);
      if(d < kr - t[p<<1|1].l + 1) return search1(p<<1|1,mid+1,kr);
      else return search1(p<<1,kl,mid);
    }
}

int search2(int p,int kl,int kr)
{
    if(t[p].l == kl && t[p].r == kr && kl == kr && t[p].v == 0) return kl;
    if(t[p].l == kl && t[p].r == kr && kl == kr && t[p].v == 1) return n+1;
    int mid = (t[p].l + t[p].r) >> 1;
    if(kr <= mid) return search2(p<<1,kl,kr);
    else if(kl > mid) return search2(p<<1|1,kl,kr);
    else
    {
      int d = query(p,kl,t[p<<1].r);
      if(d < t[p<<1].r - kl + 1) return search2(p<<1,kl,mid);
      else return search2(p<<1|1,mid+1,kr);
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    rep(i,1,n) pd[i] = 1;
    rep(i,1,m)
    {
    //rep(i,1,n) printf("%d ",pd[i]);enter;
    char c;
    cin >> c;
    if(c == 'D')
    {
        scanf("%d",&x);
        modify(1,x,0);
        des[++head] = x;
    }
    else if(c == 'R') x = des[head--],modify(1,x,1);
    else
    {
        scanf("%d",&x);
        if(!pd[x])
        {
          printf("0
");
          continue;
        }
        if(x == 1) k1 = search2(1,x+1,n),printf("%d
",k1-1);
        else if(x == n) k2 = search1(1,1,x-1),printf("%d
",n-k2);
        else
        {
          k1 = search1(1,1,x-1);
          k2 = search2(1,x+1,n);
          printf("%d
",k2-k1-1);
        }
    }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/captain1/p/9636920.html