JZOJ 4605 排序【NOIP2016模拟7.11】
2016-08-10 19:46
399 查看
排序
题目描述
输入格式
输出格式
样例输入
6 31 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.
相关文章推荐
- JZOJ 4606 序列【NOIP2016模拟7.11】
- JZOJ 4604 树【NOIP2016模拟7.11】
- 【NOIP2016模拟7.11】排序
- 【NOIP2016模拟7.11】排序
- 【NOIP2016模拟7.11】树 [bzoj] 4551: [Tjoi2016&Heoi2016]树
- 【bzoj4551】【NOIP2016模拟7.11】树
- JZOJ 4622 亚瑟王之宫【NOIP2016A组模拟7.13】
- JZOJ 5232【NOIP2017模拟】带权排序(概率,线段树)
- JZOJ 3737. 【NOI2014模拟7.11】挖宝藏(treasure)
- 【TJOI & HEOI 2016】【JZOJ 4605】 【BZOJ 4552】排序
- 【JZOJ 4605】【BZOJ 4552】排序
- 【jzoj5232】【NOIP2017模拟A组模拟8.5】【带权排序】【线段树】
- [jzoj4585]【NOIP2016模拟7.7】Robert 的军队
- JZOJ 4586 Ned 的难题【NOIP2016模拟7.7】
- JZOJ 100037【NOIP2017提高A组模拟7.11】后缀数组
- JZOJ3736【NOI2014模拟7.11】数学题(math)
- JZOJ.4605. 排序
- 【NOIP2016模拟7.11】树 题解+代码
- [jzoj4598]【NOIP2016模拟7.9】准备食物
- 【JZOJ3736】【NOI2014模拟7.11】数学题(math)