vijos1112小胖的奇偶(并查集,区间转两端线段)

program xiaopang;
const maxn=65533;//maxn最好大一点,65533可以
var father,hash:array[1..maxn shl 2]of longint;
    ch:char;
    l,i,x,y,n,ans:longint;
label 1;
function h(x:longint):longint; //hash,需要学习!注意数组也要定成1..maxn(开放寻址法)
var i:longint;
begin
 i:=x mod maxn;
 while (hash[i]<>-1)and(hash[i]<>x) do
  i:=i+1;
 hash[i]:=x;
 h:=i;
end;

function find(x:longint):longint;//本题在于变区间为1..i一组数的差的奇偶性问题,构造巧妙,合并不变
var t:longint;
begin
 if father[x]=x then exit(x);
 t:=father[x];      //凡找父亲一定要写路径压缩
 father[x]:=find(t);
 exit(father[x]);
end;
procedure union(x,y:longint);
var a,b:longint;
begin
 a:=find(x);
 b:=find(y);
 if a<>b then
  father[a]:=b;
end;
begin
 readln(l);
 readln(n);
 for i:=1 to maxn shl 2 do
  begin
   father[i]:=i;
   hash[i]:=-1;
  end;
 for i:=1 to n do
  begin
   readln(x,ch,y,ch,ch);
   x:=h(x-1);
   y:=h(y);
   if ch='e' then
    begin
     if find(x)=find(y+maxn) then
      begin
       writeln(ans);
       goto 1;//exit;
      end;
     union(x,y);
     union(x+maxn,y+maxn);//这里保证了判断矛盾时只要判断一种,应为两种一定同时存在或不存在
    end;
   if ch='o' then
    begin
     if find(x)=find(y) then
      begin
       writeln(ans);
       goto 1;//exit;
      end;
     union(x,y+maxn);
     union(x+maxn,y);
    end;
   ans:=ans+1;
  end;
 writeln(ans);
 1:
end.

你可能感兴趣的:(hash,并查集)