ZJU P1610 count the colors

    xiaoxiao2021-04-13  28

    题目大意: 在一条长度0~8000的线段上染色,每次把区间[l,r]染成某种颜色。显然,后面染上去的颜色会覆盖掉之前的颜色,求染色完以后,每种颜色在这条线段上有多少个间断的区间。

    颜色不重复 0<=l<=r<=8000 1<=n,颜色类型 <=8000

    题解: 线段树: 1.就是一个普通的线段树改一下,建树要用0~8000开始建。 tree[p]=-2表示它所对应的区间[l,r]未被染色过。 tree[p]=-1代表它所对应的区间[l,r]的lazy操作已经做了。 除了上面以外,tree[p]都表示区间[l,r]的颜色。 2.用一个递归求解。 注意: 题目是一个线段而不是一个个点。 例:假设数据输入的区间大小都在0~4之间, 初始 -2 X(-2) -2 X(-2) -2 X(-2) -2 X(-2) -2 (X()表示间隔颜色,-2表示无颜色) 覆盖0~4 颜色为0,即 0 X(0) 0 X(0) 0 X(0) 0 X(0) 0 覆盖0~2 颜色为1,即 1 X(1) 1 X(1) 1 X(0) 0 X(0) 0 覆盖3~4 颜色为2,即 1 X(1) 1 X(1) 1 X(0) 2 X(2) 2 这时候 0颜色的有1个,1颜色的有1个,2颜色的有一个,而如果当成点来算的话,那么就忽略了间隔,这时候0颜色就不会被找到。

    var tree:array [0..30000] of longint; sum:array [0..8001] of longint; i,n,a,b,c:longint; procedure insert(p,l,r,a,b:longint); var mid:longint; begin mid:=(l+r) div 2; if (a=l) and (b=r) then tree[p]:=c else begin if tree[p]<>-1 then begin tree[p * 2]:=tree[p]; tree[p*2+1]:=tree[p]; tree[p]:=-1; end; if b<=mid then insert(p*2,l,mid,a,b) else if a>=mid then insert(p*2+1,mid,r,a,b) else begin insert(p * 2,l,mid,a,mid); insert(p*2+1,mid,r,mid,b); end; end; end; procedure count(p,l,r:longint); var mid:longint; begin mid:=(l+r) div 2; if tree[p]=-2 then begin c:=-2; exit; end else if (tree[p]<>c) and (tree[p]<>-1) then begin c:=tree[p]; inc(sum[c]); end else if (r-l=1) and (c=tree[p]) then exit else if tree[p]=-1 then begin count(p * 2,l,mid); count(p*2+1,mid,r); end; end; procedure print; begin for i:=0 to 8000 do if sum[i]<>0 then writeln(i,' ',sum[i]); writeln; end; begin while not eof do begin fillchar(sum,sizeof(sum),0); for i:=0 to 30000 do tree[i]:=-2; readln(n); for i:=1 to n do begin readln(a,b,c); insert(1,0,8000,a,b); end; c:=-3; count(1,0,8000); print; end; end.
    转载请注明原文地址: https://ju.6miu.com/read-668788.html

    最新回复(0)