【NOIP模拟】Baby Step

题目

Description

从前有一个Baby。
从前还有一个网格图。
Baby 喜欢爆炸。
Baby 偶尔会炸掉网格图中的一条边(u, v)。之后他会尝试从u 走到v。
如果他成功地从u 走到v,他会很高兴;否则他会找人打架。
从第二次爆炸开始,根据Baby 此时心情的不同,Baby 会炸掉不同的边。
你被要求编写一个程序,对于每次爆炸,给出此时Baby 是否还能从u 到v。

Input

第一行,一个整数R,代表网格图是R*R 的。
第二行,一个整数N,代表操作数。
第三行,四个整数x1,y1,x2,y2,描述了第一次爆炸的边。
以下N-1 行,每行四个整数x1,y1,x2,y2,x1’,y1’,x2’,y2’,分别描述Baby 高兴时炸的边和
想找人打架时炸的边。

Output

输出N 行,如果本次爆炸后Baby 高兴,输出一行“HAHA”,否则输出一行“DAJIA”

Sample Input

2
2
1 1 1 2
1 1 2 1 1 2 2 2

Sample Output

HAHA
DAJIA

Data Constraint

对于40%的数据,R≤50。
对于100%的数据,1≤R≤500,1≤N≤2R^2-2R。
对于100%的数据,1≤x1,x2,x1’,x2’≤R,1≤y1,y2,y1’,y2’≤R。
对于所有对边的描述,要么x1=x2 且|y1-y2|=1,要么y1=y2 且|x1-x2|=1。
保证所有边至多被删除一次。
均匀地,对于50%的数据,x1=x1’,y1=y1’,x2=x2’,y2=y2’。
请注意输入输出规模较大。

题解

首先发现这一题是动态的删边,然后问你这一条将要被删的边是不是桥
可以发现这道题设置了强制在线
那么似乎没有什么算法可以处理这个问题,应该是一道神奇的思路题
考虑把每一个被4条边圈起来的一个空间成为“域”
那么我们每一次删边就相当于把两个域连了起来
如果这两个域本来就连了起来,那么这条边就是一个桥
为什么呢?
考虑到两个域在这之前已经连了起来,那么它们之间必定有一条类似于“半圆”的道路,而这条道路上的边都已经被删了,而且这个东西把两个点包了起来
也就是说如果不走将要删的边而是要走其他路径一定会装上那个“半圆”
所以我们并查集处理一下每一个域的连接情况

贴代码

var
    fa:array[0..200005]of longint;
    a:array[0..200005]of longint;
    x,y,x1,y1:longint;
    i,j,k,l,r,n,m:longint;
    bz:boolean;
function getfather(x:longint):longint;
begin
    if fa[x]=x then exit(x) else
    fa[x]:=getfather(fa[x]);
    exit(fa[x]);
end;
procedure make;
var
    i,j,k,yu1,yu2,fa1,fa2:longint;
begin
    if x=x1 then
    begin
        if y>y1 then
        begin
            k:=y;
            y:=y1;
            y1:=k;
        end;
        yu1:=(x-1)*(r-1)+y;
        yu2:=yu1-r+1;
        if yu2<0 then yu2:=0;
    end else
    begin
        if x>x1 then
        begin
            k:=x;
            x:=x1;
            x1:=k;
        end;
        yu1:=(x-1)*(r-1)+y;
        yu2:=yu1-1;
        if yu1 mod (r-1)=1 then
        begin
            if y=1 then yu2:=0 else yu1:=0;
        end;
        if yu2<0 then yu2:=0;
    end;
    if yu1>(r-1)*(r-1) then yu1:=0;
    fa1:=getfather(yu1);
    fa2:=getfather(yu2);
    if fa1<>fa2 then
    begin
        bz:=false;
        writeln('HAHA');
        fa[fa1]:=fa2;
    end else
    begin
        bz:=true;
        writeln('DAJIA');
    end;
end;
begin
    //assign(input,'t2.in'); reset(input);
    readln(r);
    readln(n);
    readln(x,y,x1,y1);
    for i:=0 to (r-1)*(r-1) do fa[i]:=i;
    make;
    for i:=1 to n-1 do
    begin
        if bz=false then readln(x,y,x1,y1,l,l,l,l)
        else readln(x,y,x1,y1,x,y,x1,y1);
        make;
    end;
    //close(input);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值