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]排序-二分+线段树的更多相关文章

  1. 【BZOJ4552】[Tjoi2016&Heoi2016]排序 二分+线段树

    [BZOJ4552][Tjoi2016&Heoi2016]排序 Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ...

  2. bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  3. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  4. bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序

    http://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案 把>=mid 的数看做1,<mid 的数看做0 这样升序.降序排列相当于 ...

  5. BZOJ4552 [Tjoi2016&Heoi2016]排序 【二分 + 线段树】

    题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ...

  6. BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  7. 2018.08.01 BZOJ4552: [Tjoi2016&Heoi2016]排序(二分+线段树)

    传送门 线段树简单题. 二分答案+线段树排序. 实际上就是二分答案mid" role="presentation" style="position: relat ...

  8. BZOJ4552 Tjoi2016&Heoi2016排序 【二分+线段树】*

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个 ...

  9. [BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)

    二分答案mid,将>=mid的设为1,<mid的设为0,这样排序就变成了区间修改的操作,维护一下区间和即可 然后询问第q个位置的值,为1说明>=mid,以上 时间复杂度O(nlog2 ...

随机推荐

  1. dede被注入后台提示用户名不存在解决方法

    如果已经发现/data,有很长一个txt记事本,说明已经被其他人SQL注入了,或是已经有人进行尝试SQL注入了了. 记事儿本如:75252sdaswfdfsfq538ef2ad3556_safe.tx ...

  2. ThinkPhp5.0_文件上传

    ===================================================================== 路径: F:\wamp\www\public\uploads ...

  3. Html5+js测试题【完整版】

    一.闭包的理解:使用闭包主要是为了设计私有的方法和变量.闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露.闭包三个特性: 1.函数嵌套函数 ; 2 ...

  4. async函数解析

    转载请注明出处:async函数解析 async函数是基于Generator函数实现的,也就是说是Generator函数的语法糖.在之前的文章有介绍过Generator函数语法和异步应用,如果对其不了解 ...

  5. Java中的对象Object方法之---wait()和notifiy()

    这一篇咋们继续,接着来介绍wait()和notify()方法,我们都知道这两个方法和之前介绍的方法不太一样,那就是这两个方法是对象Object上的,不属于Thread类上的.我们也知道这两个方法是实现 ...

  6. Discuz论坛URL静态化规则urlrewrite

    http://blog.csdn.net/u014181418/article/details/53467980 1.在论坛代码目录下新建文件".htaccess" vim /us ...

  7. 基于BCGP库的界面效果

  8. python初识-day2

    1.模块初识 python中的库包括标准库和第三方库,需要使用时可直接导入,导入格式为"import  库模块",例如: import sys #sys为python的标准库 pr ...

  9. 交换两个变量的值,不借助第三个变量的 三种方法(JS实现)

    第一种:算术运算法 var a = 10; var b = 12; a = b - a; b = b - a; a = b + a; 它的原理是:把a.b看做数轴上的点,围绕两点间的距离来进行计算.具 ...

  10. 【转】Matlab中的括号()[] {}

    Matlab中经常会用到括号去引用某Array或者是cell的内容,但三者有什么具体区别呢?] []