【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]
排序
Time Limit: 60 Sec Memory Limit: 256 MB
[Submit][Status][Discuss]
Description
Input
Output
输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。
Sample Input
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
Sample Output
HINT
1 <= n <= 10^5,1 <= m <= 10^5, 1 <= q <= n。
Solution
我们先考虑如果权值很小的话怎么做,显然可以对每个权值开一个线段树维护在哪些位置出现过。
那么排序显然就是覆盖连续的一段。只要知道某一区间有几个这个权值即可。
但是这样显然是过不了的,于是我们考虑二分答案,把val >= mid的设为1,其余的设为0。
这样就把权值变成了0/1,那么显然我们按照以上操作,如果Q位置上是1说明mid<=Ans,还可以更大一点,否则说明mid>Ans。
只要支持区间求和以及区间覆盖0/1即可。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ;
const int MOD = 1e9 + ; int get()
{
int res = , Q = ; char c;
while( (c = getchar()) < || c > )
if(c == '-') Q = -;
if(Q) res = c - ;
while( (c = getchar()) >= && c <= )
res = res * + c - ;
return res * Q;
} int n, m, Q;
int a[ONE];
int res, now; struct power
{
struct point
{
int val, tag;
}Node[ONE]; void Build(int i, int l, int r)
{
Node[i].tag = -;
if(l == r) return;
int mid = l + r >> ;
Build(i << , l, mid);
Build(i << | , mid + , r);
} int pushdown(int i, int l, int r)
{
int mid = l + r >> ;
if(Node[i].tag != -)
{
Node[i << ].tag = Node[i].tag;
Node[i << ].val = Node[i].tag * (mid - l + );
Node[i << | ].tag = Node[i].tag;
Node[i << | ].val = Node[i].tag * (r - (mid + ) + );
Node[i].tag = -;
}
} void Update(int i, int l, int r, int L, int R, int x)
{
if(L > R) return;
if(L <= l && r <= R)
{
Node[i].tag = x;
Node[i].val = x * (r - l + );
return;
}
pushdown(i, l, r);
int mid = l + r >> ;
if(L <= mid) Update(i << , l, mid, L, R, x);
if(mid + <= R) Update(i << | , mid + , r, L, R, x);
Node[i].val = Node[i << ].val + Node[i << | ].val;
} void Query(int i, int l, int r, int L, int R)
{
if(L > R) return;
if(L <= l && r <= R)
{
res += Node[i].val;
return;
}
pushdown(i, l, r);
int mid = l + r >> ;
if(L <= mid) Query(i << , l, mid, L, R);
if(mid + <= R) Query(i << | , mid + , r, L, R);
}
}C[]; struct operate
{
int l, r, x;
}oper[ONE]; void Modify(int id, int Left, int Right)
{
res = ;
C[id].Query(, , n, Left, Right);
C[id].Update(, , n, Left, Right, );
C[id].Update(, , n, now, now + res - , );
now += res;
} int Check(int mid)
{
for(int i = ; i <= ; i++)
C[i].Node[].tag = ; for(int i = ; i <= n; i++)
C[a[i] >= mid].Update(, , n, i, i, ); for(int i = ; i <= m; i++)
{
now = oper[i].l;
if(oper[i].x == ) for(int id = ; id <= ; id++) Modify(id, oper[i].l, oper[i].r);
if(oper[i].x == ) for(int id = ; id >= ; id--) Modify(id, oper[i].l, oper[i].r);
} res = , C[].Query(, , n, Q, Q);
return res;
} int main()
{
n = get(); m = get();
for(int i = ; i <= n; i++)
a[i] = get();
for(int i = ; i <= m; i++)
oper[i].x = get(), oper[i].l = get(), oper[i].r = get(); Q = get();
int l = , r = n;
while(l < r - )
{
int mid = l + r >> ;
if(Check(mid)) l = mid;
else r = mid;
} if(Check(r)) printf("%d", r);
else printf("%d", l);
}
【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]的更多相关文章
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...
- bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 线段树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意: 给你一个1-n的全排列,m次操作,操作由两种:1.将[l,r]升序排序,2 ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树
题目链接 题面 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- HDU 5649 DZY Loves Sorting(二分答案+线段树/线段树合并+线段树分割)
题意 一个 \(1\) 到 \(n\) 的全排列,\(m\) 种操作,每次将一段区间 \([l,r]\) 按升序或降序排列,求 \(m\) 次操作后的第 \(k\) 位. \(1 \leq n \le ...
- [BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)
二分答案mid,将>=mid的设为1,<mid的设为0,这样排序就变成了区间修改的操作,维护一下区间和即可 然后询问第q个位置的值,为1说明>=mid,以上 时间复杂度O(nlog2 ...
- [HEOI2016/TJOI2016] 排序 解题报告(二分答案/线段树分裂合并+set)
题目链接: https://www.luogu.org/problemnew/show/P2824 题目描述: 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在 ...
- 【Luogu】P2824排序(二分答案+线段树排序)
题目链接 震惊!两个线段树和一个线段树竟是50分的差距! 本题可以使用二分答案,二分那个位置上最后是什么数.怎么验证呢? 把原序列改变,大于等于mid的全部变成1,小于mid的全部变成0,之后线段树排 ...
- bzoj 4552 [Tjoi2016&Heoi2016]排序——二分答案
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成 ...
- YbtOJ#463-序列划分【二分答案,线段树,dp】
正题 题目链接:https://www.ybtoj.com.cn/problem/463 题目大意 给出长度为\(n\)的序列\(A,B\).要求划分成若干段满足 对于任何\(i<j\),若\( ...
随机推荐
- goroutine与channels
goroutine(协程) 大家都知道java中的线程Thread,golang没有提供Thread的功能,但是提供了更轻量级的goroutine(协程),协程比线程更轻,创办一个协程很简单,只需要g ...
- (一)java数据类型图
┏数值型━┳━整数型:byte short int long ┏基本数据类型━━┫ ┗━浮点型:float double ...
- 解决因生成javadoc失败导致Maven打包失败问题
方案就是设置javadoc生成失败时不导致整个打包失败: <plugin> <groupId>org.apache.maven.plugins</groupId> ...
- nginx 几个常用的标准模块介绍
ngx_http_ssl_module(https) 1:指明是否启用的虚拟主机的ssl功能 ssl on | off; 2:指明虚拟主机使用的证书文件 ssl_certificate /usr/lo ...
- Struts2(七)
以下内容是基于导入struts2-2.3.32.jar包来讲的 1.xml验证 Struts2提供了验证器,实现了通用的验证逻辑.例如: 非空验证器.长度验证器.日期验证器.email验证器等.具体定 ...
- html5兼容
You can download the latest version of HTML5shiv from github or reference the CDN version at https:/ ...
- C#和Java在多态情况下对成员访问的比较
本文简单比较一下两种语言在里氏替换原则下,父类引用变量访问成员时的访问结果: 如果有两个类,如Person与Student,后者继承了前者,而且子类与父类有重名成员,当Person p = new S ...
- 【C++】深度探索C++对象模型读书笔记--关于对象(Object Lessons)
前言中的内容: 1.什么是C++对象模型? 1.语言中直接支持面向对象程序设计的部分 2. 对于各种支持的底层实现机制 2. C++ class的完整virtual functions在编译时期就固定 ...
- 【Django】Django—Form两种解决表单数据无法动态刷新的方法
一.无法动态更新数据的实例 1. 如下,数据库中创建了班级表和教师表,两张表的对应关系为“多对多” from django.db import models class Classes(models. ...
- CF464C-Substitutes in Number
题意 开始给出一个长为\(n\)的数字串,有\(m\)次操作按顺序执行,每次把当前数字串中的某一个数码替换成一个数字串\(t\)(可以为空或多位),最后问操作结束后的数字串十进制下模\(10^9+7\ ...