bzoj2738

时间:2021-10-06 07:42:49

感人肺腑pascal过不去系列,跪求开O2
先不说这个了,学完cdq分治之后又顺手学了一下整体二分
感觉这两个东西很多相似的地方,干脆都叫cdq分治好了
二分解决k小就是设当前二分的答案为m,把x<=m的标为1,统计区间和,如果大于等于k,说明答案小于等于m,否则大于m
其实仔细想想主席树就是方便干这个事,但这题主席树?总觉得有点虚
什么叫整体二分,就是二分答案,把答案能<=m归为1类,另外归为一类,划分成子问题继续解决(分治的策略)
统计和可以用二维树状数组
还是由于没开O2和pascal跑得慢,实在弄不过去,有算法上优化的话欢迎指教
代码仅供参考,因为TLE……

 type node=record
x,y,v:longint;
end;
point=record
x0,y0,x1,y1,k:longint;
end; var q:array[..] of point;
ans,d,c:array[..] of longint;
v:array[..] of boolean;
a:array[..] of node;
w:array[..] of longint;
b:array[..,..] of longint;
mx,n,m,i,j,k,p:longint; function lowbit(x:longint):longint;
begin
exit(x and (-x));
end; procedure add(x,y,w:longint);
var p:longint;
begin
p:=x;
while y<=n do
begin
x:=p;
while x<=n do
begin
inc(b[x,y],w);
x:=x+lowbit(x);
end;
y:=y+lowbit(y);
end;
end; function ask(x,y:longint):longint;
var p:longint;
begin
ask:=; p:=x;
while y> do
begin
x:=p;
while x> do
begin
ask:=ask+b[x,y];
x:=x-lowbit(x);
end;
y:=y-lowbit(y);
end;
end; function check(i:longint):boolean;
var s:longint;
begin
s:=ask(q[i].x1,q[i].y1);
if s<q[i].k then exit(false);
s:=s-ask(q[i].x0-,q[i].y1);
if s<q[i].k then exit(false);
s:=s+ask(q[i].x0-,q[i].y0-);
if s<q[i].k then exit(false);
s:=s-ask(q[i].x1,q[i].y0-);
if s>=q[i].k then exit(true) else exit(false);
end; procedure swap(var a,b:node);
var c:node;
begin
c:=a;
a:=b;
b:=c;
end; procedure sort(l,r:longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ].v;
repeat
while a[i].v<x do inc(i);
while x<a[j].v do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure work(f,t,l,r:longint);
var m,p,l1,l2:longint;
begin
// writeln(f,' ',r,' ',l,' ',r);
if f>t then exit;
if l>r then exit;
m:=(l+r) shr ;
while (j<k) and (a[j+].v<=m) do
begin
add(a[j+].x,a[j+].y,);
inc(j);
end;
while (j>) and (a[j].v>m) do
begin
add(a[j].x,a[j].y,-);
dec(j);
end;
p:=;
for i:=f to t do
if check(c[i]) then
begin
inc(p);
ans[c[i]]:=m;
v[i]:=true;
end
else v[i]:=false; l1:=f; l2:=f+p;
for i:=f to t do
if v[i] then
begin
d[l1]:=c[i];
inc(l1);
end
else begin
d[l2]:=c[i];
inc(l2);
end;
for i:=f to t do c[i]:=d[i];
work(l1,t,m+,r);
work(f,l1-,l,m-);
end; begin
readln(n,m);
for i:= to n do
for j:= to n do
begin
inc(k);
a[k].x:=i;
a[k].y:=j;
read(a[k].v);
end;
sort(,k);
p:=;
w[]:=a[].v;
a[].v:=;
for i:= to k do
begin
if w[p]<>a[i].v then
begin
inc(p);
w[p]:=a[i].v;
end;
a[i].v:=p;
end;
for i:= to m do
begin
with q[i] do readln(x0,y0,x1,y1,k);
c[i]:=i;
end;
j:=;
work(,m,,p);
for i:= to m do
writeln(w[ans[i]]);
end.

相关文章