题目大意

  给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:(0,l,r)表示将区间[l,r]的数字升序排序;(1,l,r)表示将区间[l,r]的数字降序排序。最后询问第q位置上的数字。n<=30000。

题解

  关键词:反演。

  我们假设最后q位置上的值为val。此时我们对整个序列进行排序...我们发现除了val外,其它点之间的顺序并不重要,只有其他点与val的相对大小才有意义。所以我们将原序列中位置上的值小于val的的值设为0,大于等于的设为1,整个序列上每个点的值表示的就是序列上的原值与val的大小关系。这样对01值排序用覆盖式的线段树来进行排序过程最方便了(具体看代码中的Sort)。

  此时q位置上的值如果是0,则说明当前的val比答案大;若此时q位置上的值是1,则说明当前的val小于或等于答案。也就是说,val越大,最后q位上的值越有可能是0,val越小,q位上的值越有可能是1。因此我们可以用UpperBound二分得出答案。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std; const int MAX_N = 30010, MAX_NODE = MAX_N * 4, MAX_OP = 30010;
int OrgData[MAX_N];
int N, TotOp, P; struct RangeTree
{
private: struct Node
{
int Sum, Cover;
}_nodes[MAX_NODE];
int N; void PushDown(int cur, int l, int r)
{
if (_nodes[cur].Cover >= 0)
{
_nodes[cur * 2].Cover = _nodes[cur].Cover;
_nodes[cur * 2 + 1].Cover = _nodes[cur].Cover; int mid = (l + r) / 2;
_nodes[cur * 2].Sum = _nodes[cur].Cover * (mid - l + 1);
_nodes[cur * 2 + 1].Sum = _nodes[cur].Cover * (r - mid); _nodes[cur].Cover = -1;
}
} void PullUp(int cur)
{
_nodes[cur].Sum = _nodes[cur * 2].Sum + _nodes[cur * 2 + 1].Sum;
} void Update(int cur, int al, int ar, int sl, int sr, int cover)
{
assert(al <= sr && ar >= sl && sl <= sr);
if (al <= sl && sr <= ar)
{
_nodes[cur].Cover = cover;
_nodes[cur].Sum = cover * (sr - sl + 1);
return;
}
PushDown(cur, sl, sr);
int mid = (sl + sr) / 2;
if (al <= mid)
Update(cur * 2, al, ar, sl, mid, cover);
if (ar > mid)
Update(cur * 2 + 1, al, ar, mid + 1, sr, cover);
PullUp(cur);
} int Query(int cur, int al, int ar, int sl, int sr)
{
assert(al <= sr && ar >= sl && sl <= sr);
if (al <= sl && sr <= ar)
return _nodes[cur].Sum;
PushDown(cur, sl, sr);
int mid = (sl + sr) / 2, ans = 0;
if (al <= mid)
ans += Query(cur * 2, al, ar, sl, mid);
if (ar > mid)
ans += Query(cur * 2 + 1, al, ar, mid + 1, sr);
PullUp(cur);
return ans;
} void InitBuild(int cur, int sl, int sr, int *a)
{
if (sl == sr)
{
_nodes[cur].Sum = a[sl];
_nodes[cur].Cover = -1;
return;
}
int mid = (sl + sr) / 2;
InitBuild(cur * 2, sl, mid, a);
InitBuild(cur * 2 + 1, mid + 1, sr, a);
_nodes[cur].Cover = -1;
PullUp(cur);
} public: void Init(int n, int *a)
{
N = n;
InitBuild(1, 1, N, a);
} void Update(int l, int r, int cover)
{
if (l > r)
return;
Update(1, l, r, 1, N, cover);
} int Query(int l, int r)
{
return Query(1, l, r, 1, N);
}
}g; struct Oper//operation
{
int L, R;
bool IsUp; Oper(){}
Oper(int l, int r, int isUp):L(l),R(r),IsUp(isUp){}
}_ops[MAX_OP]; void Sort(Oper op)
{
int sum1 = g.Query(op.L, op.R);
if (op.IsUp)
{
g.Update(op.R - sum1 + 1, op.R, 1);
g.Update(op.L, op.R - sum1, 0);
}
else
{
g.Update(op.L, op.L + sum1 - 1, 1);
g.Update(op.L + sum1, op.R, 0);
}
} bool AnsNotLesser(int val)
{
static int a[MAX_N];
for (int i = 1; i <= N; i++)
a[i] = (OrgData[i] >= val);
g.Init(N, a); for (int i = 1; i <= TotOp; i++)
Sort(_ops[i]);
return g.Query(P, P) == 1;
} int UpperBound(int l, int r, bool(*InRange)(int))
{
while (l < r)
{
int mid = (l + r + 1) / 2;
if (InRange(mid))
l = mid;
else
r = mid - 1;
}
return l;
} int main()
{
scanf("%d%d", &N, &TotOp);
for (int i = 1; i <= N; i++)
scanf("%d", OrgData + i);
for (int i = 1; i <= TotOp; i++)
{
int l, r, isDown;
scanf("%d%d%d", &isDown, &l, &r);
_ops[i] = Oper(l, r, !isDown);
}
scanf("%d", &P);
printf("%d\n", UpperBound(1, N, AnsNotLesser));
return 0;
}

  

luogu2828 [HEOI2016/TJOI2016]排序的更多相关文章

  1. 洛谷 P2824 [HEOI2016/TJOI2016]排序 解题报告

    P2824 [HEOI2016/TJOI2016]排序 题意: 有一个长度为\(n\)的1-n的排列\(m\)次操作 \((0,l,r)\)表示序列从\(l\)到\(r\)降序 \((1,l,r)\) ...

  2. [HEOI2016/TJOI2016]排序 线段树+二分

    [HEOI2016/TJOI2016]排序 内存限制:256 MiB 时间限制:6000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而 ...

  3. [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)

    题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...

  4. 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)

    2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...

  5. [HEOI2016&TJOI2016] 排序(线段树)

    4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2703  Solved: 1386[S ...

  6. [HEOI2016/TJOI2016]排序

    嘟嘟嘟 首先这题的暴力是十分好写的,而且据说能得不少分. 正解写起来不难,就是不太好想. 根据做题经验,我想到了给这个序列转化成01序列,但是接下来我就不会了.还是看了题解. 因为查询只有一个数,所以 ...

  7. 【线段树合并】【P2824】 [HEOI2016/TJOI2016]排序

    Description 给定一个长度为 \(n\) 的排列,有 \(m\) 次操作,每次选取一段局部进行升序或降序排序,问你一波操作后某个位置上的数字是几 Hint \(1~\leq~n,~m~\le ...

  8. 【[HEOI2016/TJOI2016]排序】

    巧妙思路题 有一个重要的思想就是把大于某一个数的数都变成\(1\),小于这个数的都变成\(0\),这个只有\(0\)和\(1\)的序列就很好处理了 由于我们只需要在最后求出一个位置上是什么数就可以了, ...

  9. BZOJ4552:[HEOI2016/TJOI2016]排序——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4552 https://www.luogu.org/problemnew/show/P2824 在2 ...

随机推荐

  1. Android ScrollView里嵌套RecyclerView时,在RecyclerView上滑动时出现卡顿(冲突)的现象

    最近在项目中遇到一个现象,一个界面有一个RecyclerView(GridView型的),外面套了一层ScrollView,通过ScrollView上下滚动,但是在滑动的时候如果是在RecyclerV ...

  2. JavaScript的相关知识

      Oject.assign()   // Cloning an object var obj = { a: 1 }; var copy = Object.assign({}, obj); conso ...

  3. [Android]异常2-Unexpected error while executing

    异常原因: 可能一>Android Studio的自动编译没有成功 解决方法有: 解决一>菜单栏里的“Build”,“Clean Project” 注:

  4. canves应用

    canves用得好可以有好多效果: html:<canvas id="myCanvas" width="700" height="300&quo ...

  5. 用nginx实现分布式限流

    1.前言 一般对外暴露的系统,在促销或者黑客攻击时会涌来大量的请求,为了保护系统不被瞬间到来的高并发流量给打垮, 就需要限流 . 本文主要阐述如何用nginx 来实现限流. 听说 Hystrix 也可 ...

  6. On branch master nothing to commit, working tree clean ERROR: Repository not found. fatal: Could not read from remote repository.

    将gitbash部署hexo到github:hexo deploy 报以下错误: Administrator@liu MINGW64 /Hexo $ hexo d INFO Deploying: gi ...

  7. 【剑指Offer】65、矩阵中的路径

      题目描述:   请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经 ...

  8. python中enumerate( )函数的使用

    enumerate( )函数是遍历一个序列中的元素以及元素对应的下标 seq = ['one', 'two', 'three'] for i, element in enumerate(seq): p ...

  9. windows桌面远程工具连接Ubuntu

    1.Ubuntu安装:sudo apt-get install xrdp    sudo apt-get install vnc4server sudo apt-get install xubuntu ...

  10. 【codeforces 509C】Sums of Digits

    [题目链接]:http://codeforces.com/contest/509/problem/C [题意] 给你一个数组b[i] 要求一个严格升序的数组a[i]; 使得a[i]是b[i]各个位上的 ...