[TJOI&HEOI2016]排序
2016-07-11 14:45
567 查看
题目大意
有一个n的排列,进行m次操作,每次操作是将一个区间升序或降序排序。请你输出m次操作后第p个位置的值。
数据范围
n,m≤100000分析
直接排序肯定不好做。但是如果考虑二分答案,那么问题就变成判断最后第p个位置的值是否小于等于一个数了。
所以对于当前二分的答案mid,把a[i]≤mid的都赋值为1,a[i]>mid的赋为0。以升序排序为例,求出区间有多少个1,假设共有cnt个,那么把这些1放在区间左边cnt个位置,右边的位置全部放0。这部分用线段树解决。
时间复杂度O(nlog2n)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=100005,maxt=262205; int n,m,a[maxn],q,l,r,mid,L[maxn],R[maxn],typ[maxn],t[maxt],mask[maxt]; void insert(int l,int r,int a,int b,int v,int x) { if (l==a && r==b) { mask[x]=v; t[x]=(r-l+1)*mask[x]; return; } int mid=(l+r)/2; if (mask[x]>=0) { mask[x*2]=mask[x]; mask[x*2+1]=mask[x]; t[x*2]=mask[x]*(mid-l+1); t[x*2+1]=mask[x]*(r-mid); mask[x]=-1; } if (b<=mid) insert(l,mid,a,b,v,x*2); else if (a>mid) insert(mid+1,r,a,b,v,x*2+1); else { insert(l,mid,a,mid,v,x*2); insert(mid+1,r,mid+1,b,v,x*2+1); } t[x]=t[x*2]+t[x*2+1]; } int getsum(int l,int r,int a,int b,int x) { if (l==a && r==b) return t[x]; int mid=(l+r)/2; if (mask[x]>=0) { mask[x*2]=mask[x]; mask[x*2+1]=mask[x]; t[x*2]=mask[x]*(mid-l+1); t[x*2+1]=mask[x]*(r-mid); mask[x]=-1; } if (b<=mid) return getsum(l,mid,a,b,x*2); if (a>mid) return getsum(mid+1,r,a,b,x*2+1); return getsum(l,mid,a,mid,x*2)+getsum(mid+1,r,mid+1,b,x*2+1); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=0;i<m;i++) scanf("%d%d%d",&typ[i],&L[i],&R[i]); scanf("%d",&q); for (l=1,r=n,mid=(l+r)/2;l<r;mid=(l+r)/2) { memset(t,0,sizeof(t)); memset(mask,255,sizeof(mask)); for (int i=1;i<=n;i++) insert(1,n,i,i,(a[i]<=mid),1); for (int i=0;i<m;i++) { int cnt=getsum(1,n,L[i],R[i],1); if (!typ[i]) { if (cnt) insert(1,n,L[i],L[i]+cnt-1,1,1); if (cnt<R[i]-L[i]+1) insert(1,n,L[i]+cnt,R[i],0,1); }else { if (cnt) insert(1,n,R[i]-cnt+1,R[i],1,1); if (cnt<R[i]-L[i]+1) insert(1,n,L[i],R[i]-cnt,0,1); } } if (getsum(1,n,q,q,1)) r=mid;else l=mid+1; } printf("%d\n",l); return 0; }
相关文章推荐
- 一个基于Extjs 3的支持单元格合并的面板
- session入库
- 自定义一个filter,在顶点shader 定义rgb转yuv的矩阵
- <LeetCode> 题2:n阶乘尾部零的个数
- Linux 工具
- Swift -banner滚动图自定义
- Linux内存管理--基本概念【转】
- java生成随机数
- OpenStack白皮书 新机遇:容器与OpenStack(一)
- Java常用类库——正则表达式
- 各种算法 排序 查找 等等
- 关于网站访问速度调优指南
- 总结一下java volatile
- 每天一个设计模式(2):观察者模式
- Linux内存管理之mmap详解 【转】
- Android6.0的phone应用源码分析(1)——智能手机的硬件结构介绍
- 结构体
- java web笔记——javaBean&EL表达式
- 【NOIP2016模拟7.11】树 题解+代码
- [JZOJ4594] [UVa12345] Dynamic len(带修改莫队算法模板)