HDU5283 线段树

题意就不讲了,挺好理解的。。暴力很好打。。
其实正解一眼看出来是线段树。。。
题目关键在于在 x 轴和 y 轴上,鱼的坐标变化都是单调的,因为 d 是正值。我们把在一个
矩形内部有多少个点的询问拆分成四个在某个点的左下角有多少个点的询问,然后用一棵线
段树维护鱼的 x 坐标,一棵线段树维护鱼的 y 坐标。对于移动操作,在对应的线段树上进行
区间更新,更新完成后询问该区间内的最大值,若最大值超过了我们关心的值,那么这个点
就可以删掉了,删除的方法可以通过在对应的线段树上把值设为-INF,同时继续询问直到
最大值不大于我们关心的值为止。那么我们就可以实时维护当前在我们关心的点左下角的点
有哪些了,这可以再借助于一个树状数组。这样子作四遍我们就能得到最终的答案了。
代码等一下在贴,,,正在调试。。
来了,,写的好长,,说实话A的时候一脸蒙蔽。。以为要调好久才能A。。结果蜜汁AC。。发现有人打了10000多b,orz

uses math;
type tree=record
    maxx,maxy,sum:array[0..3]of int64;
    addx,addy:int64;
end;
const maxn=100100;
    inf=-2147483647;
var
    x,y:array[0..4]of longint;
    ans:int64;
    typ,d,tl,tr1,n,m,t,xx1,xx2,yy1,yy2,i,j:longint;
    tx,ty:array[0..maxn]of longint;
    tr:array[0..maxn shl 2]of tree;
procedure pushup(rt:longint);
var
    i:longint;
begin
    for i:=0 to 3 do
    begin
                tr[rt].maxx[i]:=max(tr[rt<<1].maxx[i],tr[rt<<1 or 1].maxx[i]);
                tr[rt].maxy[i]:=max(tr[rt<<1].maxy[i],tr[rt<<1 or 1].maxy[i]);
                tr[rt].sum[i]:=tr[rt<<1].sum[i]+tr[rt<<1 or 1].sum[i];
        end;
end;
procedure pushdown(rt:longint);
var
    i:longint;
begin
        if(tr[rt].addx<>0)then
    begin
                tr[rt<<1].addx:=tr[rt<<1].addx+tr[rt].addx;
                inc(tr[rt<<1 or 1].addx,tr[rt].addx);
                for i:=0 to 3 do
            begin
                        tr[rt<<1].maxx[i]:=tr[rt<<1].maxx[i]+tr[rt].addx;
                        tr[rt<<1 or 1].maxx[i]:=tr[rt<<1 or 1].maxx[i]+tr[rt].addx;
                end;
                tr[rt].addx:=0;
        end;
        if(tr[rt].addy<>0)then
    begin
                inc(tr[rt<<1].addy,tr[rt].addy);
                inc(tr[rt<<1 or 1].addy,tr[rt].addy);
        for i:=0 to 3 do
        begin
                        inc(tr[rt<<1].maxy[i],tr[rt].addy);
                        inc(tr[rt<<1 or 1].maxy[i],tr[rt].addy);
                end;
                tr[rt].addy:=0;
        end;
end;
procedure build(l,r,rt:longint);
var
    mid,i:longint;
begin
        tr[rt].addy:=0;
    tr[rt].addx:=0;
        if(l=r)then
    begin
        for i:=0 to 3 do
        begin
                        tr[rt].maxx[i]:=tx[l];
                        tr[rt].maxy[i]:=ty[l];
                        tr[rt].sum[i]:=1;
                end;
                exit;
        end;
        mid:=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1 or 1);
        pushup(rt);
end;
procedure update(l1,r1,rt,l,r:longint;v:int64;flag:longint);
var
    mid,i:longint;
begin
        if(l<=l1)and(r1<=r)then
    begin
                if(flag=0)then
            begin
                    for i:=0 to 3 do
                        inc(tr[rt].maxx[i],v);
                        inc(tr[rt].addx,v);
                end
                else
                begin
                    for i:=0 to 3 do
                inc(tr[rt].maxy[i],v);
                        inc(tr[rt].addy,v);
                end;
                exit;
        end;
        pushdown(rt);
        mid:=(l1+r1)>>1;
        if(l<=mid)then update(l1,mid,rt<<1,l,r,v,flag);
        if(r>mid)then update(mid+1,r1,rt<<1 or 1,l,r,v,flag);
        pushup(rt);
end;
procedure adjust(l,r,rt:longint);
var
    mid,i:longint;
begin
        mid:=(l+r)>>1;
    for i:=0 to 3 do
    begin
        if(tr[rt].maxx[i]>x[i])or(tr[rt].maxy[i]>y[i])then
    begin
            if(l=r)then
        begin
                tr[rt].maxx[i]:=inf+1;
                tr[rt].maxy[i]:=inf+1;
                tr[rt].sum[i]:=0;
                continue;
            end;
            pushdown(rt);
            adjust(l,mid,rt<<1);
        adjust(mid+1,r,rt<<1 or 1);
            pushup(rt);
        end;
    end;
end;
function query(l1,r1,rt,l,r,f:longint):int64;
var
    mid:longint;
    ans:int64;
begin
        if(l<=l1)and(r1<=r)then
    exit(tr[rt].sum[f]);
        mid:=(l1+r1)>>1;
        ans:=0;
        if(l<=mid)then ans:=ans+query(l1,mid,rt<<1,l,r,f);
        if(r>mid)then ans:=ans+query(mid+1,r1,rt<<1 or 1,l,r,f);
        exit(ans);
end;
begin
        read(t);
    for j:=1 to t do
    begin
                readln(n);
        readln(xx1,yy1,xx2,yy2);
                x[0]:=xx2;
        y[0]:=yy2;
                x[1]:=xx1-1;
        y[1]:=yy2;
                x[2]:=xx2;
        y[2]:=yy1-1;
                x[3]:=xx1-1;
            y[3]:=yy1-1;
        for i:=1 to n do
        begin
                        readln(tx[i],ty[i]);
                end;
                build(1,n,1);
                read(m);
            while m<>0 do
                begin
            read(typ);
                        if(typ=1)then
                    begin
                                readln(tl,tr1,d);
                                update(1,n,1,tl,tr1,int64(d),0);
                        end;
                        if(typ=2)then
                    begin
                                readln(tl,tr1,d);
                                update(1,n,1,tl,tr1,int64(d),1);
                        end;
                        if(typ=3)then
            begin
                                adjust(1,n,1);
                                readln(tl,tr1);
                                ans:=query(1,n,1,tl,tr1,0)-query(1,n,1,tl,tr1,1)-query(1,n,1,tl,tr1,2)+query(1,n,1,tl,tr1,3);
                                writeln(ans);
                        end;
                        dec(m);
                end;
        end;
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值