(线段树)HDU-1540 Tunnel Warfare

 

During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.

Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!

抗日战争期间,华北平原广大地区广泛开展了隧道战。一般说来,由隧道连接的村庄是一条线。除了两端的两个村庄,每个村庄都与相邻的两个村庄直接相连。


入侵者经常袭击一些村庄,并摧毁其中的部分隧道。八路军指挥官要求获得隧道和村庄的最新连接状态。如果一些村庄被严重隔离,必须立即恢复连接!

Input

The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.

There are three different events described in different format shown below:

D x: The x-th village was destroyed.

Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.

R: The village destroyed last was rebuilt.

输入的第一行包含两个正整数n和m(n,m≤50000),表示村庄和事件的数量。接下来的M行中的每一行描述一个事件。

有三种不同的事件以不同的格式描述,如下所示:

D x:第x村被摧毁了。
Q x:军区要求x村直接或间接联系的村庄数量,包括其自身。

R:上次被摧毁的村庄是重建的。

Output

Output the answer to each of the Army commanders’ request in order on a separate line.

将每个陆军指挥官请求的答案按顺序输出到单独的行中。

Sample Input

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

Sample Output

1
0
2
4

 

断断续续写了三天

坑点的话,一个村庄被摧毁多次,用栈保存的话,重建的时候要进行判断

 

杭电习惯坑,实际每次有多组数据,记得memset

询问就是找到你的村庄,然后左右查找能延伸多远

代码如下,已AC

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
#include <stack>
#include<cstdio>
#include<cmath>


using namespace std;

stack<int>A;
struct nod{
    int l,r;//记录一个区间内,从左数和从右数最长连续

}node[200000];

void build(int l,int r,int p){
    if(l==r){
        node[p].l=1;
        node[p].r=1;
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,p<<1);
    build(mid+1,r,(p<<1)+1);
    node[p].l=node[p].r=node[p<<1].r+node[(p<<1)+1].l;



}

void dest(int l,int r,int p,int c){
    //printf("* ");
    if(l==r&&l==c){
        node[p].l=0;
        node[p].r=0;
        return ;
    }
    int mid=(l+r)/2;
    if(mid>=c)
        dest(l,mid,p<<1,c);
    if(c>mid)
        dest(mid+1,r,(p<<1)+1,c);
    if(node[(p<<1)+1].l==r-mid)//这里卡了好久,后来发现了,之前错在去判断l和r是否相等
        node[p].r=node[p<<1].r+node[(p<<1)+1].l;
     else
        node[p].r=node[(p<<1)+1].r;
     if(node[p<<1].l==mid-l+1)
        node[p].l=node[p<<1].l+node[(p<<1)+1].l;
    else
        node[p].l=node[p<<1].l;

}
void rebulit(int l,int r,int p,int c){//毁灭和重建可以合起来写,懒得改了
    if(l==r&&l==c){
        node[p].l=1;
        node[p].r=1;
        return ;
    }
    int mid=(l+r)/2;
   if(mid>=c)
        rebulit(l,mid,p<<1,c);
    if(c>mid)
        rebulit(mid+1,r,(p<<1)+1,c);
   if(node[(p<<1)+1].l==r-mid)
        node[p].r=node[p<<1].r+node[(p<<1)+1].l;
     else
        node[p].r=node[(p<<1)+1].r;
     if(node[p<<1].l==mid-l+1)
        node[p].l=node[p<<1].l+node[(p<<1)+1].l;
    else
        node[p].l=node[p<<1].l;



}
int ans=0;
int ll=0,rr=0;
void query(int l,int r,int p,int c){
   int mid =(l+r)/2;
   if(l==r){
    if(node[p].l)
        ll=rr=1;
    else
        ll=rr=0;
    ans=node[p].l;
    return ;
   }
   if(c<=mid){
        query(l,mid,p<<1,c);
        if(rr)
            ans+=node[(p<<1)+1].l;
        if(node[(p<<1)+1].l<r-mid) rr=0;
   }
  else{
    query(mid+1,r,(p<<1)+1,c);
    if(ll)
        ans+=node[p<<1].r;
    if(node[p<<1].r<mid-l+1) ll=0;
   }

}


int main()
{
   int n,m,w;
   char c;
   int haha[100000]={0};
  while(~scanf("%d%d",&n,&m)){
    ans=0;ll=0;rr=0;
    for(int i=0;i<200000;i++){
        node[i].l=node[i].r=0;
    }
    while(!A.empty()) A.pop();
    build(1,n,1);
//    for(int i=0;i<20;i++)
//                        printf("%d %d\n",node[i].l,node[i].r);
       for(int i=0;i<m;i++){
            getchar();
            scanf("%c",&c);
            if(c=='R'){
                if(A.empty())
                    break;
                while(!A.empty()){
                int num=A.top();
                A.pop();
                    if(haha[num]==1){
                        haha[num]=0;
                        rebulit(1,n,1,num);
                        break;
                    }
                }
            }
            else{
                scanf("%d",&w);
                if(c=='D'){
                    haha[w]=1;
                    A.push(w);
               //     printf("=====");
                    dest(1,n,1,w);

                }
                if(c=='Q'){
                    query(1,n,1,w);
                    printf("%d\n",ans);
                }
            }
                                for(int i=0;i<20;i++)
              printf("%d %d\n",node[i].l,node[i].r);
   }
  }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值