[HEOI2016/TJOI2016]排序 线段树+二分
[HEOI2016/TJOI2016]排序
内存限制:256 MiB 时间限制:6000 ms 标准输入输出
题目类型:传统 评测方式:文本比较题目描述
输入格式
输出格式
样例
题解:
思路挺神仙的
这题你要是真的去排序就死了。。。
但我们还是要用到线段树
但和tree这道kruscal一样思路非常神奇
我们二分q位置上的数
每一次二分,维护一个线段树,
我们设当前分到的数是x,那么我们让所有大于等于x的叶节点为1,小于x为0
这样我们维护区间中有几个1,
如果升序排序我们就把前一段暴力改成1,后一段改成0,降序反过来
这样我们查询q位置是什么数
如果是1,则当前二分的x可能偏小,但可能就是答案,要用mid更新ans,因为我们是让大于等于x的节点为1,
如果是0,则说明当前x偏大,应查询较小的数
每次二分都这样检查一遍,二分结束的ans就是答案
反套路题,多多积累
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> #define int long long #define MAXN 100005 using namespace std; int n,m,a[MAXN],q,l,r,ans; struct node{ int opt,l,r; }ask[MAXN]; struct Segtree{ int l,r,val,laz; }tree[MAXN<<2]; void down( int k){ if (tree[k].laz==-1) return ; tree[k<<1].laz=tree[k].laz; tree[k<<1|1].laz=tree[k].laz; tree[k<<1].val=(tree[k<<1].r-tree[k<<1].l+1)*tree[k].laz; tree[k<<1|1].val=(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].laz; tree[k].laz=-1; } void build( int k, int l, int r, int x){ tree[k].l=l,tree[k].r=r; tree[k].laz=-1; if (l==r){ if (a[l]>=x) tree[k].val=1; else tree[k].val=0; return ; } int mid=(l+r)>>1; build(k<<1,l,mid,x); build(k<<1|1,mid+1,r,x); tree[k].val=tree[k<<1].val+tree[k<<1|1].val; } int query( int k, int opl, int opr){ int l=tree[k].l,r=tree[k].r; if (opl<=l&&r<=opr){ return tree[k].val; } down(k); int mid=(l+r)>>1; if (opr<=mid) return query(k<<1,opl,opr); if (opl>mid) return query(k<<1|1,opl,opr); return query(k<<1,opl,mid)+query(k<<1|1,mid+1,opr); } void change( int k, int opl, int opr, int val){ int l=tree[k].l,r=tree[k].r; if (opl<=l&&r<=opr){ tree[k].val=(r-l+1)*val; tree[k].laz=val; return ; } down(k); int mid=(l+r)>>1; if (opr<=mid) change(k<<1,opl,opr,val); else if (opl>mid) change(k<<1|1,opl,opr,val); else { change(k<<1,opl,opr,val); change(k<<1|1,opl,opr,val); } tree[k].val=tree[k<<1].val+tree[k<<1|1].val; } bool check( int x){ build(1,1,n,x); for ( int i=1;i<=m;i++){ int sum=query(1,ask[i].l,ask[i].r); if (sum==0||sum==ask[i].r-ask[i].l+1) continue ; if (!ask[i].opt){ change(1,ask[i].l,ask[i].r-sum,0); change(1,ask[i].r-sum+1,ask[i].r,1); } else { change(1,ask[i].l,ask[i].l+sum-1,1); change(1,ask[i].l+sum,ask[i].r,0); } } return query(1,q,q); } signed main(){ scanf ( "%lld%lld" ,&n,&m); for ( int i=1;i<=n;i++) scanf ( "%lld" ,&a[i]); for ( int i=1;i<=m;i++){ scanf ( "%lld%lld%lld" ,&ask[i].opt,&ask[i].l,&ask[i].r); } scanf ( "%lld" ,&q); l=1,r=n; while (l<=r){ int mid=(l+r)>>1; if (check(mid)) ans=mid,l=mid+1; else r=mid-1; } printf ( "%lld\n" ,ans); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
· drools 规则引擎和 solon-flow 哪个好?solon-flow 简明教程