排序HEOI2016/TJOI2016 二分+线段树判定
LINK:排序 此题甚好我一点思路都没有要是我当时省选此题除了模拟我恐怕想不到还可以二分 还可以线段树。。。
有点ex 不太好写 考虑 暴力显然每次给出询问我们都是可以直接sort的 无视地形无视一切直接sort 。复杂度mnlogn 30分到手。
考虑更为优秀的做法 桶排序 每次排序都是O(n)总体复杂度 nm 50分到手
考虑 不模拟做题 不断排序肯定是行不通的 如何 改变问题模型是关键之处。
然鹅 很难想到解法 思路引导一下 0 1 序列线段树树是很容易支持排序的 区间修改区间查询即可。再考虑答案是否具有单调性 从数值大小来说答案虽然是确定的 但是 显然也具有单调性(虽然有点牵强
但是我们可以不断地缩小答案的 取值范围 从而寻找到答案这是关键,从答案的值域角度来说的确可以二分。想办法不断缩小答案的值域,怎么办?
考虑最终拍好序的队列>=mid 为1 反之为0 那么我们把整个操作倒序的实现其实就是0 1 的不断排序。且最后询问的位置一定为1。因为>=当前答案。
考虑如果答案较大那么经过0 1 的排序之后最后询问的位置一定不为1 所以我们成功的缩小的值域 从而达到判定mid的效果二分可行 排序01串用上述方法搞就好了。
写完了 码力最近下降很多 可能 打代码的时候 精力不够吧。
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<ctime>
- #include<algorithm>
- #include<cctype>
- #include<utility>
- #include<queue>
- #include<map>
- #include<set>
- #include<bitset>
- #include<deque>
- #include<vector>
- #include<cstdio>
- #include<cstdlib>
- #include<iomanip>
- #include<stack>
- #include<string>
- #include<cstring>
- #define INF 1000000000
- #define ll long long
- #define db double
- #define max(x,y) ((x)>(y)?(x):(y))
- #define min(x,y) ((x)>(y)?(y):(x))
- #define sum(x) t[x].sum
- #define cnt(x) t[x].cnt
- #define l(x) t[x].l
- #define r(x) t[x].r
- #define tag(x) t[x].tag
- #define op(i) s[i].op
- #define x(i) s[i].x
- #define y(i) s[i].y
- #define zz p<<1
- #define yy p<<1|1
- using namespace std;
- char buf[<<],*fs,*ft;
- inline char getc()
- {
- return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
- }
- inline int read()
- {
- int x=,f=;char ch=getchar();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
- return x*f;
- }
- const int MAXN=;
- int n,m,pos,sum0,sum1;
- int a[MAXN],b[MAXN];
- struct wy
- {
- int l,r;
- int sum,cnt;
- int tag;
- }t[MAXN<<];
- struct data{int op,x,y;}s[MAXN];
- inline void build(int p,int l,int r)
- {
- l(p)=l;r(p)=r;tag(p)=-;
- if(l==r){sum(p)=b[l];cnt(p)=b[l]^;return;}
- int mid=(l+r)>>;
- build(zz,l,mid);
- build(yy,mid+,r);
- sum(p)=sum(zz)+sum(yy);
- cnt(p)=cnt(zz)+cnt(yy);
- }
- inline void pushdown(int p)
- {
- int mid=(l(p)+r(p))>>;
- if(tag(p)==)
- {
- sum(zz)=(mid-l(p)+);
- cnt(zz)=;
- sum(yy)=r(p)-mid;
- cnt(yy)=;
- tag(zz)=tag(yy)=;
- tag(p)=-;return;
- }
- sum(zz)=;
- cnt(zz)=(mid-l(p)+);
- sum(yy)=;
- cnt(yy)=r(p)-mid;
- tag(yy)=tag(zz)=;
- tag(p)=-;return;
- }
- inline void change(int p,int l,int r,int x)
- {
- if(l>r)return;
- if(l<=l(p)&&r>=r(p))
- {
- if(x==)
- {
- sum(p)=r(p)-l(p)+;
- cnt(p)=;tag(p)=;
- return;
- }
- cnt(p)=r(p)-l(p)+;
- sum(p)=;tag(p)=;
- return;
- }
- if(tag(p)!=-)pushdown(p);
- int mid=(l(p)+r(p))>>;
- if(l<=mid)change(zz,l,r,x);
- if(r>mid)change(yy,l,r,x);
- sum(p)=sum(zz)+sum(yy);
- cnt(p)=cnt(zz)+cnt(yy);
- }
- inline void ask(int p,int l,int r)
- {
- if(l<=l(p)&&r>=r(p))
- {
- sum0+=cnt(p);
- sum1+=sum(p);
- return;
- }
- if(tag(p)!=-)pushdown(p);
- int mid=(l(p)+r(p))>>;
- if(l<=mid)ask(zz,l,r);
- if(r>mid)ask(yy,l,r);
- return;
- }
- inline int check(int x)
- {
- for(int i=;i<=n;++i)b[i]=a[i]>=x?:;
- build(,,n);
- for(int i=;i<=m;++i)
- {
- sum0=sum1=;
- ask(,x(i),y(i));
- if(!op(i))//0升序
- {
- //cout<<x(i)<<' '<<x(i)+sum0-1<<endl;
- //cout<<x(i)+sum0<<' '<<y(i)<<endl;
- change(,x(i),x(i)+sum0-,);
- change(,x(i)+sum0,y(i),);
- }
- else
- {
- change(,x(i),x(i)+sum1-,);
- change(,x(i)+sum1,y(i),);
- }
- }
- sum0=sum1=;
- ask(,pos,pos);
- return sum1;
- }
- int main()
- {
- //freopen("1.in","r",stdin);
- n=read();m=read();
- for(int i=;i<=n;++i)a[i]=read();
- for(int i=;i<=m;++i)
- {
- int op,x,y;
- op=read();x=read();y=read();
- s[i]=(data){op,x,y};
- }
- pos=read();
- int l=,r=n;
- while(l+<r)
- {
- int mid=(l+r)>>;
- if(check(mid))l=mid;
- else r=mid;
- }
- if(check(r))printf("%d\n",r);
- else printf("%d\n",l);
- return ;
- }
最后再次回顾本题这样做法的正确性 1 我们似乎找不到一种除了模拟之外更好的方法解决本题
2 强行考虑答案的单调性 发现答案的值域显然具有单调性 想办法缩小值域 直至找到答案。
3 缩小值域方法的正确性 对于>=答案的数字看成1的话反之为0 考虑最终的序列我们可以将其抽象成0 1 串那么最后答案所在位为1。每次排序的时候我们都是将1排到前面或排到后面 最终形成一个最终的序列,于是乎我们利用等效法确定了一个01串只要这个01串最后的排序满足答案的位置为1 那么当前mid就有可能合法然后二分不断地去找那个成功与不成功的边界成功的边界就是我们寻找的答案了,正确性可以理解为等效法显然是正确的 判断的正确性显然是单调(答案可以做到比答案小的也就是1的数量更多也能做到。故此方法正确。于是就成功的解决了这个看似解决不了的问题。
排序HEOI2016/TJOI2016 二分+线段树判定的更多相关文章
- BZOJ4552 [Tjoi2016&Heoi2016]排序 【二分 + 线段树】
题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ...
- BZOJ4552(二分+线段树)
要点 序列是n个不同的数,则新学到的一种策略就是二分这个位置的答案,然后可以上下调. 神奇地只关注大于还是小于mid并赋值0.1,这样m个操作的排序就能用线段树维护了! #include <cs ...
- HDU4614 Vases and Flowers 二分+线段树
分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...
- J - Joseph and Tests Gym - 102020J (二分+线段树)
题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...
- Educational Codeforces Round 61 D 二分 + 线段树
https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...
- 【BZOJ-3110】K大数查询 整体二分 + 线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6265 Solved: 2060[Submit][Sta ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)
大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...
- 【BZOJ4552】[Tjoi2016&Heoi2016]排序 二分+线段树
[BZOJ4552][Tjoi2016&Heoi2016]排序 Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ...
随机推荐
- 赋值,逻辑,运算符, 控制流程之if 判断
赋值运算 (1). 增量运算 age += 1 # age = age + 1 print(age) age -= 10 # age = age - 10 (2).交叉赋值 x = 111 y = 2 ...
- CVE-2020-5902 简单复现
这几天通报了f5的一个漏洞,想着先弄个环境保存着,说不定后面就用到了.. 1.漏洞描述 近日,F5官方发布公告,修复了流量管理用户界面(TMUI)中存在的一个远程代码执行漏洞(CVE-2020-5 ...
- 安装更强大更美观的zsh,配置oh my zsh及插件
安装更强大更美观的zsh,配置oh my zsh及插件 #0x0 安装zsh #0x1 安装oh my zsh #0x2 配置zshrc #0x3 配置主题 #0x4 安装插件 #0x5 小结 #0x ...
- matlab 打包exe
mcc -m gui_abc.m https://blog.csdn.net/hujiameihuxu/article/details/53525373 deploytool app compiler
- 表格(table)数据导出成Excel
使用xlxs-js库 function exportExcel () { var wb = XLSX.utils.table_to_book(document.querySelector('.my-e ...
- (六)pandas 日常使用技巧
pandas数据处理 1.删除重复元素 import numpy as np import pandas as pd from pandas import Series,DataFrame df = ...
- flask 源码专题(六):session处理机制
前言 flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制,flask默认的session信息保存在cookie中,不够安全和灵活 ...
- linux专题(五):常用的基本命令(三)文件内容查看
http://dwz.date/UDf 概述 Linux系统中使用以下命令来查看文件的内容: cat 由第一行开始显示文件内容 tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写! n ...
- angular浏览器兼容性问题解决方案
问题:edge浏览器下,固定列的边框消失 原因:ng-zorro-antd表格组件使用nzLeft和nzRight指令固定的表格列,这两个指令的实现css3中的标签: position: -webki ...
- 老司机带你玩转面试(3):Redis 高可用之主从模式
前文回顾 建议前面文章没看过的同学先看下前面的文章: 「老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化」 「老司机带你玩转面试(2):Redis 过期策略以及缓存雪崩.击穿. ...