您的位置:首页 > 其它

JZOJ 4605 排序【NOIP2016模拟7.11】

2016-08-10 19:46 399 查看

排序

题目描述







输入格式



输出格式



样例输入

6 3

1 6 2 5 3 4

0 1 4

1 3 6

0 2 4

3

样例输出

5

数据范围



题解

这一题,看上去很难,事实上还挺简单。

首先一开始想到的一定是用快速排序,但是这样子我们会求出所有位置上的数,然而我们只需求出某个位置上的数而已。

我们用二分,我们二分第q位置上的数。

对于每次二分,假设我们二分的数为a,将整个序列中大于等于a的值变为1,小于a的值变成0。这样序列中只有0和1。

对于每一次部分排序,我们可以通过线段树的区间更新,若为升序排序,则把该区间的0全部排在区间前段,1排在区间后段,否则反之即可。

最后全部部分排序结束后,检验位置p上的值是1还是0,来继续调整下一次二分。二分结束后,就可以知道答案了。复杂度为O(mlog2n)

Code(Pascal)

var
cqy:array[0..102000,1..3] of longint;
tr:array[0..500000,0..1] of longint;
s,la:array[0..502000] of longint;
n,m,j,k,l,i,p,qqq,r,mid,td:longint;
procedure js(o,l,r,ccc:longint);
var
mid:longint;
begin
la[o]:=-1;
if l=r then
begin
if s[l]<ccc then
begin
tr[o,0]:=1;
tr[o,1]:=0;
end
else
begin
tr[o,1]:=1;
tr[o,0]:=0;
end;
exit;
end;
mid:=(l+r) div 2;
js(o*2,l,mid,ccc);
js(o*2+1,mid+1,r,ccc);
tr[o,0]:=tr[o*2,0]+tr[o*2+1,0];
tr[o,1]:=tr[o*2,1]+tr[o*2+1,1];
end;
function cx(o,l,r,ll,rr:longint):longint;
var
mid,ls,rs:longint;
begin
mid:=(l+r) div 2;
ls:=o*2;
rs:=ls+1;
if la[o]>=0 then
begin
tr[ls,la[o]]:=mid-l+1;
tr[ls,1-la[o]]:=0;
tr[rs,la[o]]:=r-mid;
tr[rs,1-la[o]]:=0;
la[ls]:=la[o];
la[rs]:=la[o];
la[o]:=-1;
end;
if (l=ll) and (r=rr) then exit(tr[o,0]);
if rr<=mid then cx:=cx(ls,l,mid,ll,rr)
else if ll>mid then cx:=cx(rs,mid+1,r,ll,rr)
else cx:=cx(ls,l,mid,ll,mid)+cx(rs,mid+1,r,mid+1,rr);
tr[o,0]:=tr[ls,0]+tr[rs,0];
tr[o,1]:=tr[ls,1]+tr[rs,1];
end;
procedure xg(o,l,r,ll,rr,kkk:longint);
var
ls,mid,rs:longint;
begin
ls:=o*2;
rs:=ls+1;
mid:=(l+r) div 2;
if (l=ll) and (r=rr) then
begin
la[o]:=kkk;
tr[o,kkk]:=r-l+1;
tr[o,1-kkk]:=0;
exit;
end;
if la[o]>=0 then
begin
tr[ls,la[o]]:=mid-l+1;
tr[ls,1-la[o]]:=0;
tr[rs,la[o]]:=r-mid;
tr[rs,1-la[o]]:=0;
la[ls]:=la[o];
la[rs]:=la[o];
la[o]:=-1;
end;
if rr<=mid then xg(ls,l,mid,ll,rr,kkk)
else if ll>mid then xg(rs,mid+1,r,ll,rr,kkk)
else
begin
xg(ls,l,mid,ll,mid,kkk);
xg(rs,mid+1,r,mid+1,rr,kkk);
end;
tr[o,0]:=tr[ls,0]+tr[rs,0];
tr[o,1]:=tr[ls,1]+tr[rs,1];
end;
function ok(o:longint):boolean;
var
i,j,k,l,p:longint;
begin
js(1,1,n,o);
for i:=1 to m do
begin
p:=cx(1,1,n,cqy[i,2],cqy[i,3]);
if cqy[i,1]=0 then
begin
if p>0 then
xg(1,1,n,cqy[i,2],cqy[i,2]+p-1,0);
if p<cqy[i,3]-cqy[i,2]+1 then
xg(1,1,n,cqy[i,2]+p,cqy[i,3],1);
end
else
begin
p:=(cqy[i,3]-cqy[i,2]+1)-p;
if p>0 then
xg(1,1,n,cqy[i,2],cqy[i,2]+p-1,1);
if p<cqy[i,3]-cqy[i,2]+1 then
xg(1,1,n,cqy[i,2]+p,cqy[i,3],0);
end;
end;
P:=CX(1,1,N,QQQ,QQQ);
if p=1 then exit(false) else exit(true);
end;
begin
readln(n,m);
for i:=1 to n do
read(s[i]);
for i:=1 to m do
begin
readln(cqy[i,1],cqy[i,2],cqy[i,3]);
if cqy[i,2]>cqy[i,3] then
begin
td:=cqy[i,2];
cqy[i,2]:=cqy[i,3];
cqy[i,3]:=td;
end;
end;
readln(qqq);
l:=1;
r:=n;
while l+1<r do
begin
mid:=(l+r) div 2;
if ok(mid) then l:=mid
else r:=mid;
end;
if ok(n) then l:=n;
writeln(l);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: