[poj2528]求最后未完全被其它线段覆盖的线段个数
大意:给出N<=10000个线段,每个数l,r<=10000000,求最后未被完全覆盖的线段条数。
解答:先离散化,再线段树,每次记录一下每个区间被那一个覆盖,最后扫一遍即可。
program poj2528; Type re=record l,r,cover:longint; end; Var a:array[0..20000] of re; z:array[0..40000] of longint; n,o,all,i,top:longint; f:array[0..180000] of re; t:array[0..20000] of boolean; ans:longint; Function max(a,b:longint):longint; begin if a>b then exit(a) else exit(b); end; Function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end; Procedure lsh(var a:array of longint;k:longint); Type rec=record pos:longint; num:longint; end; Var b:array[0..100000] of rec; i,now,last:longint; Procedure qsort(var b:array of rec;l,r:longint); var i,j:longint; x,y:rec; begin i:=l;j:=r;x:=b[random(r-l+1)+l]; repeat while b[i].num<x.num do inc(i); while b[j].num>x.num do dec(j); if i<=j then begin y:=b[i]; b[i]:=b[j]; b[j]:=y; inc(i); dec(j); end; until i>j; if l<j then qsort(b,l,j); if i<r then qsort(b,i,r); end; begin for i:=1 to k do with b[i] do begin num:=a[i]; pos:=i; end; qsort(b,1,k); now:=1; a[b[1].pos]:=1; last:=1; for i:=2 to k do begin if b[i-1].num<>b[i].num then begin last:=i; inc(now); end; a[b[i].pos]:=now; end; end; Procedure build(p:longint); begin if f[p].l=f[p].r then exit; f[p*2].l:=f[p].l; f[p*2].r:=(f[p].l+f[p].r) div 2; f[p*2+1].l:=(f[p].l+f[p].r) div 2+1; f[p*2+1].r:=f[p].r; build(p*2); build(p*2+1); end; Procedure pushdata(P:longint); begin if f[p].cover<>0 then begin f[p*2].cover:=f[p].cover; f[p*2+1].cover:=f[p].cover; f[p].cover:=0; end; end; Procedure insert(p,pl,pr,v:longint); var mid:longint; begin // writeln('#',p,' ',pl,' ',pr,' ',v,' ',f[p].l,' ',f[p].r); if (f[p].l=pl) and (f[p].r=pr) then begin f[p].cover:=v; exit; end; pushdata(p); mid:=(f[p].l+f[p].r) div 2; if pl<=mid then insert(p*2,pl,min(mid,pr),v); if pr>mid then insert(p*2+1,max(mid+1,pl),pr,v); end; Procedure visit(P:longint); begin // writeln(p,' ',f[p].l,' ',f[p].r,' ',f[p].cover); if f[p].cover<>0 then begin t[f[p].cover]:=true; exit; end; if f[p].l=f[p].r then exit; visit(p*2); visit(p*2+1); end; begin readln(o); for all:=1 to o do begin readln(n); for i:=1 to n do begin readln(a[i].l,a[i].r); z[i*2-1]:=a[i].l; z[i*2]:=a[i].r; end; lsh(z,n*2); for i:=1 to n*2 do if i mod 2=1 then a[(i-1) div 2+1].l:=z[i] else a[(i-1) div 2+1].r:=z[i]; fillchar(f,sizeof(f),0); f[1].l:=1; f[1].r:=40000; build(1); for i:=1 to n do insert(1,a[i].l,a[i].r,i); fillchar(t,sizeof(t),false); top:=1; while f[top].r>=2*n do top:=top*2; top:=top div 2; visit(top); ans:=0; for i:=1 to n do if t[i] then inc(ans); writeln(ans); end; end.