博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序
阅读量:6985 次
发布时间:2019-06-27

本文共 3529 字,大约阅读时间需要 11 分钟。

 

二分答案

把>=mid 的数看做1,<mid 的数看做0

这样升序、降序排列相当于区间查询0,1 的个数,区间覆盖0,1

线段树即可完成

查询给定位置p

如果=1,说明p位置的数>=mid ,上调下界

如果=0,说明p位置的数<mid,下调上界

 

#include
#include
#include
using namespace std;#define N 100001int n,m,p;int a[N],MID;int sum0[N<<2],sum1[N<<2],flag[N<<2];int tot0,tot1;struct node{ int ty,l,r;}e[N];void read(int &x){ x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }}void build(int k,int l,int r){ sum0[k]=sum1[k]=0; flag[k]=-1; if(l==r) { if(a[l]>=MID) sum1[k]++; else sum0[k]++; return; } int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); sum0[k]=sum0[k<<1]+sum0[k<<1|1]; sum1[k]=sum1[k<<1]+sum1[k<<1|1];}void down(int k,int l,int mid,int r){ if(!flag[k]) { sum0[k<<1]=mid-l+1; sum1[k<<1]=0; sum0[k<<1|1]=r-mid; sum1[k<<1|1]=0; } else { sum1[k<<1]=mid-l+1; sum0[k<<1]=0; sum1[k<<1|1]=r-mid; sum0[k<<1|1]=0; } flag[k<<1]=flag[k<<1|1]=flag[k]; flag[k]=-1;}void query(int k,int l,int r,int opl,int opr){ if(l>=opl && r<=opr) { tot0+=sum0[k]; tot1+=sum1[k]; return; } int mid=l+r>>1; if(flag[k]!=-1) down(k,l,mid,r); if(opl<=mid) query(k<<1,l,mid,opl,opr); if(opr>mid) query(k<<1|1,mid+1,r,opl,opr);}void change(int k,int l,int r,int opl,int opr,int ty){ if(l>=opl && r<=opr) { if(!ty) { sum0[k]=r-l+1; sum1[k]=0; } else { sum0[k]=0; sum1[k]=r-l+1; } flag[k]=ty; return; } int mid=l+r>>1; if(flag[k]!=-1) down(k,l,mid,r); if(opl<=mid) change(k<<1,l,mid,opl,opr,ty); if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,ty); sum0[k]=sum0[k<<1]+sum0[k<<1|1]; sum1[k]=sum1[k<<1]+sum1[k<<1|1];}int ask(int k,int l,int r,int pos){ if(l==r) return sum1[k]; int mid=l+r>>1; if(flag[k]!=-1) down(k,l,mid,r); if(pos<=mid) return ask(k<<1,l,mid,pos); return ask(k<<1|1,mid+1,r,pos);}bool check(int mid){ MID=mid; build(1,1,n); for(int i=1;i<=m;++i) { tot0=tot1=0; query(1,1,n,e[i].l,e[i].r); if(!e[i].ty) { if(tot0) change(1,1,n,e[i].l,e[i].l+tot0-1,0); if(tot1) change(1,1,n,e[i].r-tot1+1,e[i].r,1); } else { if(tot1) change(1,1,n,e[i].l,e[i].l+tot1-1,1); if(tot0) change(1,1,n,e[i].r-tot0+1,e[i].r,0); } } return ask(1,1,n,p);}int main(){ read(n); read(m); for(int i=1;i<=n;++i) read(a[i]); for(int i=1;i<=m;++i) read(e[i].ty),read(e[i].l),read(e[i].r); read(p); int l=1,r=n,mid,ans; while(l<=r) { mid=MID=l+r>>1; if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } cout<

 

4552: [Tjoi2016&Heoi2016]排序

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 1478  Solved: 748
[][][]

Description

在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题
,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排
序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q
位置上的数字。

Input

输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整
数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序
排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5
,1 <= m <= 10^5
 

Output

 输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

Sample Input

6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

Sample Output

5

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/7932200.html

你可能感兴趣的文章
java从字符串中提取数字
查看>>
Cardinality Feedback
查看>>
Android App Build System
查看>>
Python yield与实现
查看>>
终端中的乐趣:6个有趣的Linux命令行工具
查看>>
【技术贴】TOMCAT,Mysql提示Unknown column 'content' in 'fi
查看>>
EBS xml publisher中文乱码
查看>>
ext-anychart饼图呈现取自数据库中的数据
查看>>
Android深入浅出系列之服务机制—1.Android中的Service
查看>>
zz:彻底解决兼容性问题:Windows 7下载安装 Visual C++ 6.0(VC6)
查看>>
MVC、MVP以及Model2[上篇]
查看>>
面试总结,坚定自己的想法
查看>>
数据库隐式类型转换
查看>>
解决WCF调用多次之后没有响应的问题 转
查看>>
【BZOJ2318】【spoj4060】game with probability Problem 概率DP
查看>>
空格&amp;nbsp在不同浏览器中显示距离不一致问题解决方法
查看>>
Nancy 学习-身份认证(Basic Authentication) 继续跨平台
查看>>
分享5个主流的HTML5开发工具
查看>>
基于Ionic2的开源项目
查看>>
QEMU-KVM中的多线程压缩迁移技术
查看>>