JZOJ 4603 颜料大乱斗【NOIP2016提高A组模拟7.15】

颜色大乱斗

题目描述

这里写图片描述

输入格式

这里写图片描述

输出格式

这里写图片描述

样例输入

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

样例输出

2
1

数据范围

这里写图片描述

题解

这一题,题目要求维护加询问区间,那我们种30棵线段树维护一段区间中每种颜色的种类数即可。
记得在打线段树时加上懒惰迁移。
统计答案和更新区间以及懒惰标记下传时,只需用 c <script type="math/tex" id="MathJax-Element-1">c</script>的时间去做就可以了,反正时间复杂度不会太大。

Code(Pascal)

const
    kt=1;
var
    ch:char;
    tj:array[0..100] of longint;
    n,c,m,i,j,k,l,o,p,ans,x,y,t,u:longint;
    la:array[0..300000] of longint;
    tr:array[0..300000,0..30] of longint;
procedure jl(o,l,r:longint);
    var
        mid:longint;
    begin
        tr[o,kt]:=r-l+1;
        if l=r then exit;
        mid:=(l+r) div 2;
        jl(o*2,l,mid);
        jl(o*2+1,mid+1,r);
    end;
procedure draw(o,l,r,ll,rr,cqy:longint);
    var
        ls,rs,i,mid:longint;
    begin
        mid:=(l+r) div 2;
        ls:=O*2;
        rs:=ls+1;
        if (l=ll) and (r=rr) then
        begin
            la[o]:=cqy;
            for i:=kt to c do
            tr[o,i]:=0;
            tr[o,cqy]:=r-l+1;
            exit;
        end;
        if la[o]>0 then
        begin
            for i:=kt to c do
            begin
                tr[ls,i]:=0;
                tr[rs,i]:=0;
            end;
            tr[ls,la[o]]:=mid-l+1;
            tr[rs,la[o]]:=r-mid;
            la[ls]:=la[o];
            la[rs]:=la[o];
            la[o]:=0;
        end;
        if rr<=mid then draw(ls,l,mid,ll,rr,cqy)
        else if ll>mid then draw(rs,mid+1,r,ll,rr,cqy)
        else
        begin
            draw(ls,l,mid,ll,mid,cqy);
            draw(rs,mid+1,r,mid+1,rr,cqy);
        end;
        for i:=kt to c do
        tr[o,i]:=tr[ls,i]+tr[rs,i];
    end;
procedure cx(o,l,r,ll,rr:longint);
    var
        ls,rs,mid,i:longint;
    begin
        if (l=ll) and (r=rr) then
        begin
            for i:=kt to c do
            tj[i]:=tj[i]+tr[o,i];
            exit;
        end;
        mid:=(l+r) div 2;
        ls:=o*2;
        rs:=ls+1;
        if la[o]>0 then
        begin
            for i:=kt to c do
            begin
                tr[ls,i]:=0;
                tr[rs,i]:=0;
            end;
            tr[ls,la[o]]:=mid-l+1;
            tr[rs,la[o]]:=r-mid;
            la[ls]:=la[o];
            la[rs]:=la[o];
            la[o]:=0;
        end;
        if rr<=mid then cx(ls,l,mid,ll,rr)
        else if ll>mid then cx(rs,mid+1,r,ll,rr)
        else
        begin
            cx(ls,l,mid,ll,mid);
            cx(rs,mid+1,r,mid+1,rr);
        end;
        for i:=kt to c do
        tr[o,i]:=tr[ls,i]+tr[rs,i];
    end;
begin
    readln(n,c,m);
    jl(1,1,n);
    for i:=1 to m do
    begin
        read(ch);
        if ch='C' then
        begin
            readln(x,y,t);
            if x>y then
            begin
                u:=x;
                x:=y;
                y:=u;
            end;
            draw(1,1,n,x,y,t);
        end
        else
        begin
            readln(x,y);
            if x>y then
            begin
                u:=x;
                x:=y;
                y:=u;
            end;
            for l:=kt to c do
            tj[l]:=0;
            cx(1,1,n,x,y);
            ans:=0;
            for l:=kt to c do
            if tj[l]>0 then inc(ans);
            writeln(ans);
        end;
    end;
end.
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值