[bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树
Brief Description
DZY有一个数列a[1..n],它是1∼n这n个正整数的一个排列。
现在他想支持两种操作:
0, l, r: 将a[l..r]原地升序排序。
1, l, r: 将a[l..r]原地降序排序。
操作完后,他会给你指定一个位置k,请你告诉他a[k]的值。
Algorithm Design
很好的一道题目, 反正我没有想到正解, 但是直接抄袭jcvb的bc题目就不太资辞了(连样例都抄也太懒了吧喂) , 附上原题地址.
这是一道良心的基础数据结构题。
我们二分a[k]的值,假设当前是mid,然后把大于mid的数字标为1,不大于mid的数字标为0。然后对所有操作做完以后检查一下a[k]位置上是0还是1。
因为只有两种值,所以操作还是不难做的。只要用一个线段树,支持区间求和、区间赋值即可。这样要排序一个区间时只要查询一下里面有几个1和几个0,然后把前半段赋值为0,后半段赋值为1即可(降序的话就是反过来)。
复杂度是\(O(mlog^2n)\)的。
这题用其他玄学做法或者用更加厉害的平衡树做法也是有可能AC的。
题解来自jcvb的官方题解
Code
#include <cstdio>
#define init int l = t[k].l, r = t[k].r, mid = (l + r) >> 1
const int maxn = 1e5 + 1e2;
int n, m, a[maxn], lambda, q;
struct seg {
  int l, r, val, cov;
} t[maxn << 4];
struct op {
  int a, b, c;
} o[maxn];
void update(int k) { t[k].val = t[k << 1].val + t[k << 1 | 1].val; }
void build(int k, int l, int r) {
  t[k].l = l, t[k].r = r, t[k].cov = -1;
  if (l == r) {
    t[k].val = a[l] > lambda;
    return;
  }
  int mid = (l + r) >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
  update(k);
}
void pushdown(int k) {
  if (t[k].cov != -1) {
    t[k << 1].cov = t[k].cov;
    t[k << 1 | 1].cov = t[k].cov;
    t[k << 1].val = (t[k << 1].r - t[k << 1].l + 1) * (t[k].cov);
    t[k << 1 | 1].val = (t[k << 1 | 1].r - t[k << 1 | 1].l + 1) * (t[k].cov);
    t[k].cov = -1;
  }
  if (t[k].l < t[k].r)
    update(k);
}
int query(int k, int x, int y) {
  init;
  pushdown(k);
  if (x <= l && r <= y)
    return t[k].val;
  int ans = 0;
  if (x <= mid)
    ans += query(k << 1, x, y);
  if (y > mid)
    ans += query(k << 1 | 1, x, y);
  return ans;
}
void modify(int k, int x, int y, int val) {
  init;
  pushdown(k);
  if (x <= l && r <= y) {
    t[k].val = (r - l + 1) * val;
    t[k].cov = val;
    return;
  }
  if (x <= mid)
    modify(k << 1, x, y, val);
  if (y > mid)
    modify(k << 1 | 1, x, y, val);
  update(k);
}
bool check(int x) {
  lambda = x;
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int opt = o[i].a, x = o[i].b, y = o[i].c;
    int tmp = query(1, x, y);
    if (opt == 0) {
      modify(1, x, y - tmp, 0);
      modify(1, y - tmp + 1, y, 1);
    } else {
      modify(1, x, x + tmp - 1, 1);
      modify(1, x + tmp, y, 0);
    }
  }
  return !query(1, q, q);
}
int main() {
#ifndef ONLINE_JUDGE
  freopen("input", "r", stdin);
#endif
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; ++i)
    scanf("%d", &a[i]);
  int l = 1, r = n;
  for (int i = 1; i <= m; i++) {
    scanf("%d %d %d", &o[i].a, &o[i].b, &o[i].c);
  }
  scanf("%d", &q);
  while (l < r) {
    int mid = (l + r) >> 1;
    if (check(mid))
      r = mid;
    else
      l = mid + 1;
  }
  printf("%d", r);
}
[bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树的更多相关文章
- 【BZOJ4552】[Tjoi2016&Heoi2016]排序 二分+线段树
		[BZOJ4552][Tjoi2016&Heoi2016]排序 Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ... 
- bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树
		Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ... 
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
		解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ... 
- bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序
		http://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案 把>=mid 的数看做1,<mid 的数看做0 这样升序.降序排列相当于 ... 
- BZOJ4552 [Tjoi2016&Heoi2016]排序  【二分 + 线段树】
		题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ... 
- BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)
		Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ... 
- 2018.08.01 BZOJ4552: [Tjoi2016&Heoi2016]排序(二分+线段树)
		传送门 线段树简单题. 二分答案+线段树排序. 实际上就是二分答案mid" role="presentation" style="position: relat ... 
- BZOJ4552 Tjoi2016&Heoi2016排序 【二分+线段树】*
		Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个 ... 
- [BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)
		二分答案mid,将>=mid的设为1,<mid的设为0,这样排序就变成了区间修改的操作,维护一下区间和即可 然后询问第q个位置的值,为1说明>=mid,以上 时间复杂度O(nlog2 ... 
随机推荐
- yarn 淘宝源安装与使用用法
			Yarn 淘宝源 yarn config set registry https://registry.npm.taobao.org -g yarn config set sass_binary_sit ... 
- arduino扩展IO与M74HC595B芯片的使用,挪车电话提示牌的设计
			2018-01-0915:39:24 视频连接 首先arduino中shiftOUT()函数的定义与说明! shiftOut()描述将一个数据的一个字节一位一位的移出.从最高有效位(最左边)或最低有效 ... 
- linux运维学习
			export 和unset 设置和取消变量 echo 的双引号和单引号的区别:双引号里的会被替换,单引号里的都会直接输出. 
- linux_目录结构
			目录的作用是什么? 1. 归档和分类 2. 区分同名文件 什么是FHS? 目录层次标准,linux目录规范标准 linux系统目录有哪些特点? 1. 逻辑上所有目录都在 / 目录下,根目录是所有目录的 ... 
- AI_神经网络监督学习
			神经网络的神奇之处在哪? 所有神经网络创造出来的价值,都是由一种机器学习,称之为监督学习, 下面这些例子神经网络效果拔群,通过深度学习获利最多的是在线广告 技术的进步来源于计算机视觉和深度学习 例如: ... 
- js_11_dom其他
			有哪些其他js? window.location.href = "跳转页面" // 不写获得本页面url,写跳转到指定页面 confirm('内容') // ... 
- 国家语言,语言代码,locale id对应表
			国家语言,语言代码,locale id对应表.比如 en_US对应的id为1033, 中文的locale=zh_CN,id=2052. Locale Languagecode LCIDstring L ... 
- sqlserver 字符串截取与拼接
			update yanan set name=name+right(phone,4) where id=56 其中right(phone,4)是截取手机号后四位,left是从左开始截取.name=nam ... 
- MySQL查看和修改表的存储引擎
			1 查看系统支持的存储引擎 show engines; 2 查看表使用的存储引擎 两种方法: a.show table status from db_name where name='table_na ... 
- 01-Go命令与基础
			什么是Go? Go是一门并发支持.垃圾回收的编译型系统编程语言,旨在创造一门具有在静态编译语言的高性能和动态的高效开之间拥有良好平衡点的一门编程语言. Go的主要特点有哪些? 类型安全和内存安全 以非 ... 
