【题解】BZOJ5168:[HAOI2014]贴海报 【线段树】

Description

Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论。为了统一管理,城市委
员 会为选民准备了一个张贴海报的electoral墙。张贴规则如下:
1.electoral墙是一个长度为N个单位的长方形,每个单位记为一个格子;
2.所有张贴的海报的高度必须与electoral墙的高度一致的;
3.每张海报以“A B”表示,即从第A个格子到第B个格子张贴海报;
4.后贴的海报可以覆盖前面已贴的海报或部分海报。
现在请你判断,张贴完所有海报后,在electoral墙上还可以看见多少张海报。
Input

第一行: N M 分别表示electoral墙的长度和海报个数
接下来M行: Ai Bi 表示每张海报张贴的位置
Output

输出贴完所有海报后,在electoral墙上还可以看见的海报数。
1 0<= N <= 10000000 1<=M<=1000 1<= Ai <= Bi <=10000000
所有的数据都是整数。数据之间有一个空格
Sample Input

100 5

1 4

2 6

8 10

3 4

7 10
Sample Output

4

【题解】
我们可以用线段树进行染色。
不过,这道题有一点比较麻烦,后贴的海报会覆盖前面贴的海报,就是颜色会覆盖。

我们不妨倒着贴海报,本来贴海报的顺序是1~m,那么我们就可以从m贴到1
我们对于每一段新的染色区间[l,r],进行线段树的update操作,当发现当前这个节点已经被染色,那么不好意思,你没得染,因为越后面贴的海报越优先;反之,这个区间归你[l,r]的。

具体还是看程序
Code:

var
    flag:boolean;
    color:array[0..40000010] of boolean;
    n,m,i,ans:longint;
    x,y:array[0..20010] of longint;

procedure update(root,tl,tr,l,r:int64);//更新操作
var
    mid:int64;

begin
    if (tl>r) or (tr<l) or color[root] then exit;//区间并不包含,或者已经有海报捷足先登,那么退出
    if (tl>=l) and (tr<=r) then//这个区间归我
    begin
        flag:=true; color[root]:=true; exit;
    end;
    mid:=(tl+tr)>>1;
    update(root<<1,tl,mid,l,r);
    update(root<<1+1,mid+1,tr,l,r);
    color[root]:=color[root<<1] and color[root<<1+1];
end;

begin
    readln(n,m);
    for i:=1 to m do
        readln(x[i],y[i]);
    for i:=m downto 1 do
    begin
        flag:=false;
        update(1,1,n,x[i],y[i]);
        if flag then  //可以染色,海报+1
            inc(ans);
    end;
    writeln(ans);
end.

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/81368685
今日推荐