校门外的区间(interval)
【问题描述】
受校门外的树这道经典问题的启发,A 君根据基本的离散数学的知识,抽象
出5 种运算维护集合S(S 初始为空)并最终输出S。现在,请你完成这道校门外的
树之难度增强版——校门外的区间。
5 种运算如下:
U T S∪T
I T S∩T
D T S-T
C T T-S
S T S⊕T
基本集合运算如下:
A∪B {x : x∈A or x∈B}
A∩B {x : x∈A and x∈B}
A-B {x : x∈A and x∉B}
A⊕B (A-B)∪(B-A)
【输入】
输入共m(m<=40000)行,每行表示一种操作第一个字符表示操作种类,之后一个空格,然后是一个区间
形如(i,j)或(i,j]或[i,j)或[i,j](0<=i<=j<=65535)
【输出】
输出最后集合S的所有区间,两个区间之间用空格分隔
线段树,我是将两个整数之间看为一个点,整数看为一个点,转换了一下区间
运用两个过程incr是把区间内所有数xor 1,fill是把区间内所有数赋成相同的值
U=fill(a,b,1)
I=fill(0,a-1,0)+fill(b+1,65535,0)
D=fill(a,b,0)
C=fill(0,a-1,0)+fill(b+1,65535,0)+incr(a,b)
S=incr(a,b)
之后查询所有点即可得到区间
program interval; const s=0; e=131071; var m,i,j,k,a,b,tot:longint; order,temp:char; p,decr,left,right:array [0..3000001] of longint; stop:array [0..3000001] of boolean; procedure build; begin inc(tot); left[tot]:=0; right[tot]:=0; p[tot]:=0; stop[tot]:=true; decr[tot]:=0; end; procedure down (now:longint); begin if left[now]=0 then begin build; left[now]:=tot; end; p[left[now]]:=p[left[now]] xor decr[now]; decr[left[now]]:=decr[left[now]] xor decr[now]; if right[now]=0 then begin build; right[now]:=tot; end; p[right[now]]:=p[right[now]] xor decr[now]; decr[right[now]]:=decr[right[now]] xor decr[now]; decr[now]:=0; end; procedure fill (a,b,point,l,r,now:longint); var mid:longint; begin if a>b then exit; if (a=l)and(b=r) then begin stop[now]:=true; decr[now]:=0; p[now]:=point; exit; end; mid:=(l+r) div 2; down(now); if stop[now] then begin decr[left[now]]:=0; p[left[now]]:=p[now]; stop[left[now]]:=true; decr[right[now]]:=0; p[right[now]]:=p[now]; stop[right[now]]:=true; stop[now]:=false; end; if b<=mid then fill(a,b,point,l,mid,left[now]) else if a>=mid+1 then fill(a,b,point,mid+1,r,right[now]) else begin fill(a,mid,point,l,mid,left[now]); fill(mid+1,b,point,mid+1,r,right[now]); end; end; procedure incr (a,b,l,r,now:longint); var mid:longint; begin if a>b then exit; if (a=l)and(b=r) then begin decr[now]:=decr[now] xor 1; p[now]:=p[now] xor 1; exit; end; mid:=(l+r) div 2; down(now); if stop[now] then begin decr[left[now]]:=0; p[left[now]]:=p[now]; stop[left[now]]:=true; decr[right[now]]:=0; p[right[now]]:=p[now]; stop[right[now]]:=true; stop[now]:=false; end; if b<=mid then incr(a,b,l,mid,left[now]) else if a>=mid+1 then incr(a,b,mid+1,r,right[now]) else begin incr(a,mid,l,mid,left[now]); incr(mid+1,b,mid+1,r,right[now]); end; end; function find (who,l,r,now:longint):longint; begin if l=r then exit(p[now]); down(now); if stop[now] then begin decr[left[now]]:=0; p[left[now]]:=p[now]; stop[left[now]]:=true; decr[right[now]]:=0; p[right[now]]:=p[now]; stop[right[now]]:=true; stop[now]:=false; end; if who<=(l+r) div 2 then exit(find(who,l,(l+r) div 2,left[now])) else exit(find(who,(l+r) div 2 + 1,r,right[now])); end; begin assign(input,'interval.in'); reset(input); assign(output,'interval.out'); rewrite(output); tot:=-1; build; while not seekeof do begin read(order); read(temp); read(temp); if temp='(' then k:=1 else k:=0; a:=0; repeat read(temp); if temp=',' then break; a:=a*10+ord(temp)-48; until false; a:=a*2+k; b:=0; repeat read(temp); if (temp=')')or(temp=']') then break; b:=b*10+ord(temp)-48; until false; if temp=')' then k:=-1 else k:=0; b:=b*2+k; readln; case order of 'U':fill(a,b,1,s,e,0); 'I':begin fill(s,a-1,0,s,e,0); fill(b+1,e,0,s,e,0); end; 'D':fill(a,b,0,s,e,0); 'C':begin fill(s,a-1,0,s,e,0); fill(b+1,e,0,s,e,0); incr(a,b,s,e,0); end; 'S':incr(a,b,s,e,0); end; end; k:=-2; for i:=0 to e do begin j:=find(i,s,e,0); if j=1 then begin if i>k+1 then begin if i and 1 = 1 then write('(') else write('['); write(i div 2,','); end; k:=i; end else if k=i-1 then begin write(i div 2); if i and 1 = 1 then write('] ') else write(') '); end; end; if k=-2 then writeln('empty set'); close(input); close(output); end.