bzoj 1935 && bzoj 4322 离线+树状数组

19 篇文章 0 订阅
4 篇文章 0 订阅

题意:给定n个点,多次询问某个矩阵中包含多少点

如果暴力二维树状数组的话O(nlogn*logn+mlogn*logn)复杂度原地爆炸

那么我们就把二维树状数组通过一些方法变成一维,就能降下去一个log

离线处理

把所有的询问按照二维树状数组的套路拆成四个,

分别把给定点的坐标和拆开后的询问按横坐标排序

对于当前询问,把x小于等于这个询问横坐标的点都加入树状数组,在树状数组中询问小于等于当前询问的纵坐标的点的个数

bzoj 1935 不用离散化..

type
        rec2=record
            x,y,op,pos:longint;
end;

type
        rec1=record
            x,y:longint;
end;

var
        a               :array[0..500010] of rec1;
        q               :array[0..2000010] of rec2;
        i,j             :longint;
        t               :array[0..10000010] of longint;
        ans             :array[0..500010] of longint;
        n,m,tot         :longint;
        x1,x2,y1,y2     :longint;

procedure add(x,v:longint);
begin
   while (x<=10000001) do
   begin
      inc(t[x],v);
      inc(x,x and (-x));
   end;
end;

function find(x:longint):longint;
var
        ans:longint;
begin
   ans:=0;
   while x>0 do
   begin
      inc(ans,t[x]);
      dec(x,x and (-x));
   end;
   exit(ans);
end;

procedure sort1(l,r:longint);
var
        i,j,xx,yy:longint;
        z:rec1;
begin
   i:=l; j:=r; xx:=a[(l+r)>>1].x; yy:=a[(l+r)>>1].y;
   while i<=j do
   begin
      while (a[i].x<xx) or ((a[i].x=xx) and (a[i].y<yy)) do inc(i);
      while (a[j].x>xx) or ((a[j].x=xx) and (a[j].y>yy)) do dec(j);
      if i<=j then
      begin
         z:=a[i]; a[i]:=a[j]; a[j]:=z;
         inc(i); dec(j);
      end;
   end;
   if i<r then sort1(i,r);
   if j>l then sort1(l,j);
end;

procedure sort2(l,r:longint);
var
        i,j,xx,yy:longint;
        z:rec2;
begin
   i:=l; j:=r; xx:=q[(l+r)>>1].x; yy:=q[(l+r)>>1].y;
   while i<=j do
   begin
      while (q[i].x<xx) or ((q[i].x=xx) and (q[i].y<yy)) do inc(i);
      while (q[j].x>xx) or ((q[j].x=xx) and (q[j].y>yy)) do dec(j);
      if i<=j then
      begin
         z:=q[i]; q[i]:=q[j]; q[j]:=z;
         inc(i); dec(j);
      end;
   end;
   if i<r then sort2(i,r);
   if j>l then sort2(l,j);
end;

begin
   read(n,m);
   for i:=1 to n do
   begin
      read(a[i].x,a[i].y);
      inc(a[i].x); inc(a[i].y);
   end;
   sort1(1,n);
   //
   for i:=1 to m do
   begin
      read(x1,y1,x2,y2);
      inc(X1); inc(x2); inc(y1); inc(y2);
      inc(tot); q[tot].x:=x1-1; q[tot].y:=y1-1; q[tot].op:=1; q[tot].pos:=i;
      inc(tot); q[tot].x:=x2; q[tot].y:=y2; q[tot].op:=1; q[tot].pos:=i;
      inc(tot); q[tot].x:=x1-1; q[tot].y:=y2; q[tot].op:=-1; q[tot].pos:=i;
      inc(tot); q[tot].x:=x2; q[tot].y:=y1-1; q[tot].op:=-1; q[tot].pos:=i;
   end;
   sort2(1,tot);
   //
   j:=1;
   for i:=1 to tot do
   begin
      while (j<=n) and (a[j].x<=q[i].x) do
      begin
         add(a[j].y,1); inc(j);
      end;
      inc(ans[q[i].pos],q[i].op*find(q[i].y));
   end;
   for i:=1 to m do writeln(ans[i]);
end.

bzoj 4322 多写个离散化即可

type
        rec1=record
             x,y,p,pos:longint;
end;

type
        rec2=record
             num,pos:longint;
end;

type
        rec3=record
             x1,y1,x2,y2:longint;
end;

var
        n,m,tot         :longint;
        i,j             :longint;
        t               :array[0..600010] of int64;
        q               :array[0..400010] of rec1;
        a               :array[0..100010] of rec1;
        c               :array[0..100010] of rec3;
        b               :array[0..600010] of rec2;
        ans             :array[0..100010] of int64;

procedure add(x,v:longint);
begin
   while x<=tot do
   begin
      inc(t[x],int64(v));
      inc(x,x and (-x));
   end;
end;

function find(x:longint):int64;
var
        ans:int64;
begin
   ans:=0;
   while x>0 do
   begin
      inc(ans,t[x]);
      dec(x,x and (-x));
   end;
   exit(ans);
end;

procedure sort1(l,r:longint);
var
        i,j,x:longint;
        y:rec2;
begin
   i:=l; j:=r; x:=b[(l+r)>>1].num;
   while i<=j do
   begin
      while b[i].num<x do inc(i);
      while b[j].num>x do dec(j);
      if i<=j then
      begin
         y:=b[i]; b[i]:=b[j]; b[j]:=y;
         inc(i); dec(j);
      end;
   end;
   if i<r then sort1(i,r);
   if j>l then sort1(l,j);
end;

procedure sort2(l,r:longint);
var
        i,j,x,y:longint;
        z:rec1;
begin
   i:=l; j:=r; x:=a[(l+r)>>1].x; y:=a[(l+r)>>1].y;
   while i<=j do
   begin
      while (a[i].x<x) or ((a[i].x=x) and (a[i].y<y)) do inc(i);
      while (a[j].x>x) or ((a[j].x=x) and (a[j].y>y)) do dec(j);
      if i<=j then
      begin
         z:=a[i]; a[i]:=a[j]; a[j]:=z;
         inc(i); dec(j);
      end;
   end;
   if i<r then sort2(i,r);
   if j>l then sort2(l,j);
end;

procedure sort3(l,r:longint);
var
        i,j,x,y:longint;
        z:rec1;
begin
   i:=l; j:=r; x:=q[(l+r)>>1].x; y:=q[(l+r)>>1].y;
   while i<=j do
   begin
      while (q[i].x<x) or ((q[i].x=x) and (q[i].y<y)) do inc(i);
      while (q[j].x>x) or ((q[j].x=x) and (q[j].y>y)) do dec(j);
      if i<=j then
      begin
         z:=q[i]; q[i]:=q[j]; q[j]:=z;
         inc(i); dec(j);
      end;
   end;
   if i<r then sort3(i,r);
   if j>l then sort3(l,j);
end;

procedure lsh;
var
        i,tt:longint;
begin
   for i:=1 to n do
   begin
      b[i].num:=a[i].x; b[i].pos:=i;
      b[i+n].num:=a[i].y; b[i+n].pos:=n+i;
   end;
   for i:=1 to m do
   begin
      b[(n<<1)+i].num:=c[i].x1; b[(n<<1)+i].pos:=(n<<1)+i;
      b[(n<<1)+m+i].num:=c[i].y1; b[(n<<1)+m+i].pos:=(n<<1)+m+i;
      b[(n<<1)+m+m+i].num:=c[i].x2; b[(n<<1)+m+m+i].pos:=(n<<1)+m+m+i;
      b[(n<<1)+m+m+m+i].num:=c[i].y2; b[(n<<1)+m+m+m+i].pos:=(n<<1)+m+m+m+i;
   end;
   tt:=(n<<1)+(m<<2);
   sort1(1,tt);
   //
   tot:=1;
   if b[1].pos<=n then a[b[1].pos].x:=tot else
     if b[1].pos<=(n<<1) then a[b[1].pos-n].y:=tot else
       if b[1].pos<=(n<<1)+m then c[b[1].pos-(n<<1)].x1:=tot else
         if b[1].pos<=(n<<1)+(m<<1) then c[b[1].pos-(n<<1)-m].y1:=tot else
           if b[1].pos<=(n<<1)+m*3 then c[b[1].pos-(n<<1)-(m<<1)].x2:=tot else c[b[1].pos-(n<<1)-3*m].y2:=tot;
   for i:=2 to tt do
   begin
      if b[i].num<>b[i-1].num then inc(tot);
      if b[i].pos<=n then a[b[i].pos].x:=tot else
     if b[i].pos<=(n<<1) then a[b[i].pos-n].y:=tot else
       if b[i].pos<=(n<<1)+m then c[b[i].pos-(n<<1)].x1:=tot else
         if b[i].pos<=(n<<1)+(m<<1) then c[b[i].pos-(n<<1)-m].y1:=tot else
           if b[i].pos<=(n<<1)+m*3 then c[b[i].pos-(n<<1)-(m<<1)].x2:=tot else c[b[i].pos-(n<<1)-3*m].y2:=tot;
   end;
end;

begin
   read(n,m);
   for i:=1 to n do read(a[i].x,a[i].y,a[i].p);
   for i:=1 to m do read(c[i].x1,c[i].y1,c[i].x2,c[i].y2);
   lsh;
   //
   sort2(1,n);
   for i:=1 to m do
   begin
      q[i].x:=c[i].x1-1; q[i].y:=c[i].y1-1; q[i].p:=1; q[i].pos:=i;
      q[i+m].x:=c[i].x2; q[i+m].y:=c[i].y2; q[i+m].p:=1; q[i+m].pos:=i;
      q[i+(m<<1)].x:=c[i].x1-1; q[i+(m<<1)].y:=c[i].y2; q[i+(m<<1)].p:=-1; q[i+(m<<1)].pos:=i;
      q[i+m*3].x:=c[i].x2; q[i+m*3].y:=c[i].y1-1; q[i+m*3].p:=-1; q[i+m*3].pos:=i;
   end;
   sort3(1,m<<2);
   //
   j:=1;
   for i:=1 to m<<2 do
   begin
      while (j<=n) and (a[j].x<=q[i].x) do
      begin
         add(a[j].y,a[j].p); inc(j);
      end;
      inc(ans[q[i].pos],int64(q[i].p)*find(q[i].y));
   end;
   for i:=1 to m do writeln(ans[i]);
end.
——by Eirlys


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值