排序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年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ...
随机推荐
- css图片居中,通过纯css实现图片居中的多种实现方法
在网页布局中,图文排版是我们常用的,那么经常会遇到如何让图片居中显示呢,这篇文章将总结常用css实现图片居中的方法总结: html结构: <div class="demo" ...
- call,apply,bind的内部原理实现
call call 方法使用一个函数执行的时候更改本身 this 指向,并传入一个或者多个参数. var obj = { name: '$call' } function _fun() { conso ...
- 点分治模板 POJ 1741
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const ...
- Java编程技术之浅析Java容器技术
Java容器 集合是一种存储数据的容器,是Java开发中使用最频繁的对象类型之一. 或许提起Collection,都会第一时间意识到List和Set以及Map等相关关键词.因为这几乎是我们日常开发里接 ...
- 从0开始,手把手教你用Vue开发一个答题App
项目演示 项目演示 项目源码 项目源码 教程说明 本教程适合对Vue基础知识有一点了解,但不懂得综合运用,还未曾使用Vue从头开发过一个小型App的读者.本教程不对所有的Vue知识点进行讲解,而是手把 ...
- C#字符串拼接
var name = "李哈哈"; var t = $"我是{name}";
- 浏览器访问 www.baidu.com 的过程
浏览器访问 www.baidu.com 的过程 1 先要解析出www.baidu.com DNS域名解析为服务器 IP 2 得到 IP地址后,客户端会发起TCP请求,以及3次握手建立连接 3 建立连接 ...
- mongodb(三):数据库连接(python)
import pymongo def get_mongodb_conn(**kwargs): db_host = kwargs.get('host') db_port = kwargs.get('po ...
- Resource exhausted: OOM when allocating tensor with shape[3,3,384,384] and type float on /job:localhost/replica:0/task:0/device:GPU:0 by allocator GPU_0。。。。。
报错信息: OP_REQUIRES failed at assign_op.h:111 : Resource exhausted: OOM when allocating tensor with sh ...
- Kubernetes部署通用手册 (支持版本1.19,1.18,1.17,1.16)
Kubernetes平台环境规划 操作环境 rbac 划分(HA高可用双master部署实例) 本文穿插了ha 高可用部署的实例,当前章节设计的是ha部署双master 部署 内网ip 角色 安装软件 ...