http://poj.org/problem?id=2892

此代码在POJ上能过 在hdu上过不了

题目大意:

n个村庄相连  三种操作

D 摧毁一个村庄

Q 查询包括此村庄在内和此村庄直接和间接相连的村庄数

R 修复上一个被摧毁的村庄

Ttree 写的很烂呀

思路:

将摧毁的村庄插入二叉树中

每次询问 就查找它左边和右边最近被摧毁的村庄 就可以知道答案了

修复一个村庄 就把它在树中删除

代码及其注释:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<algorithm>
#include<stack>

using namespace std;

const int N=50010;
struct node
{
    int k;
    int l,r,f;
}mem[N];
int destroy[N];//是否被摧毁
int treehead,n;//头结点 和村庄个数
stack<int>str;//保存被摧毁的村庄
void RightTurn(int i)//右转
{
    int f=mem[i].f;
    int l=mem[i].l;
    if(f==-1)
    {
        mem[l].f=-1;
        treehead=l;
    }else
    {
        if(mem[f].l==i)
        mem[f].l=l;
        else
        mem[f].r=l;
        mem[l].f=f;
    }
    mem[i].l=mem[l].r;
    if(mem[l].r!=-1)
    mem[mem[l].r].f=i;
    mem[l].r=i;
    mem[i].f=l;
}
void LeftTurn(int i)//左转
{
    int f=mem[i].f;
    int r=mem[i].r;
    if(f==-1)
    {
        mem[r].f=-1;

        treehead=r;
    }else
    {
        if(mem[f].l==i)
        mem[f].l=r;
        else
        mem[f].r=r;
        mem[r].f=f;
    }
    mem[i].r=mem[r].l;
    if(mem[r].l!=-1)
    mem[mem[r].l].f=i;
    mem[r].l=i;
    mem[i].f=r;
}
void insert(int i,int k)//插入
{
    if(k<i)
    {
        if(mem[i].l!=-1)
        {
            insert(mem[i].l,k);
            if(mem[mem[i].l].k<mem[i].k)
            {
                RightTurn(i);
            }
        }else
        {
            mem[i].l=k;
            mem[k].f=i;
        }
    }else
    {
        if(mem[i].r!=-1)
        {
            insert(mem[i].r,k);
            if(mem[mem[i].r].k<mem[i].k)
            {
                LeftTurn(i);
            }
        }else
        {
            mem[i].r=k;
            mem[k].f=i;
        }
    }
}
void dele(int i,int k)//删除
{
    if(i<k)
    {
        dele(mem[i].r,k);
    }else if(i>k)
    {
        dele(mem[i].l,k);
    }else
    {
        int x=i;
        while(mem[x].l!=-1||mem[x].r!=-1)
        {
            if(mem[x].l!=-1)
            {
                RightTurn(x);
            }else
            {
                LeftTurn(x);
            }
        }
        if(mem[x].f==-1)
        {
            treehead=-1;return;
        }
        if(mem[mem[x].f].l==x)
        mem[mem[x].f].l=-1;
        if(mem[mem[x].f].r==x)
        mem[mem[x].f].r=-1;
    }
}
void LeastLeft(int i,int k,int *L)//求最近左被摧毁村庄
{
    if(i==-1)
    {
        return;
    }
    if(k<=i)
    {
        LeastLeft(mem[i].l,k,L);
    }else if(k>i)
    {
        *L=max(*L,i);
        LeastLeft(mem[i].r,k,L);
    }

}
void LeastRight(int i,int k,int *R)//求最近右被摧毁村庄
{
    if(i==-1)
    {
        return;
    }
    if(k<i)
    {
        *R=min(*R,i);
        LeastRight(mem[i].l,k,R);
    }else if(k>=i)
    {
        LeastRight(mem[i].r,k,R);
    }
}
void begin()//初始化一些内容
{
   while(!str.empty())
   str.pop();
   memset(destroy,0,sizeof(destroy));
   treehead=-1;
}
int main()
{
   int m;
   while(scanf("%d %d",&n,&m)!=EOF)
   {
       begin();
       char c;
       int i;
       for(int k=1;k<=m;++k)
       {
           getchar();
           scanf("%c",&c);
           if(c=='D')
           {
               scanf("%d",&i);
               mem[i].l=mem[i].r=-1;
               mem[i].k=k;
               if(treehead==-1)//如果树是空的
               {
                   treehead=i;
                   mem[i].f=-1;
               }else
               {
                   insert(treehead,i);//否则 插入
               }
               str.push(i);
               ++destroy[i];//记录
           }else if(c=='Q')
           {
               int ans,L,R;
               scanf("%d",&i);
               if(destroy[i]>0)//特殊情况
               {
                  ans=0;
               }else
               {
                   L=0;
                   LeastLeft(treehead,i,&L);
                   R=n+1;
                   LeastRight(treehead,i,&R);
                   ans=R-L-1;
               }
               printf("%d\n",ans);

           }else
           {
               if(str.empty())
               continue;
               dele(treehead,str.top());//删点 并记录
               --destroy[str.top()];
               str.pop();
           }
       }
   }
   return 0;
}

 

posted on 2012-07-15 15:35  夜->  阅读(200)  评论(0编辑  收藏  举报