1045. 快速排序(25)

时间限制
200 ms

内存限制
65536 kB

代码长度限制
8000 B

判题程序
Standard

作者
CAO, Peng

著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的N个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?

例如给定N = 5, 排列是1、3、2、4、5。则:

  • 1的左边没有元素,右边的元素都比它大,所以它可能是主元;
  • 尽管3的左边元素都比它小,但是它右边的2它小,所以它不能是主元;
  • 尽管2的右边元素都比它大,但其左边的3比它大,所以它不能是主元;
  • 类似原因,4和5都可能是主元。

    因此,有3个元素可能是主元。

    输入格式:

    输入在第1行中给出一个正整数N(<= 105); 第2行是空格分隔的N个不同的正整数,每个数不超过109

    输出格式:

    在第1行中输出有可能是主元的元素个数;在第2行中按递增顺序输出这些元素,其间以1个空格分隔,行末不得有多余空格。

    输入样例:

    5
    1 3 2 4 5
    

    输出样例:

    3
    1 4 5

题目链接:PAT 1045

最近刚刚数据结构学了快速排序,根据快速排序基本法,可以发现若一个数被选为主元,那么这一次用它划分之后它左边的数一定均小于它,右边的数均大于它,那就可以用主席树来做啦。

直接查询$A_{1}$~$A_{i-1}$范围内是否有大于key的数和$A_{i+1}$~$A_{n}$范围内是否有小于key的数即可,挺模版的一道题,当然主席树代码量比较大,用BIT求逆序数好像也行,反正大概意思理解了方法应该是多种的,记得查询的时候范围要特判一下免得无限递归,另外一个最大的坑点就是这题如果没有主元,也要有输出空行,期末快考完了,只能刷点水题了…………

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 1e5 + 7;
struct seg
{int lson, rson;int cnt;inline void reset(){lson = rson = cnt = 0;}
};
seg T[N * 20];
int root[N], arr[N], tot;
vector<int>vec, ans;void init()
{CLR(root, 0);T[0].reset();vec.clear();ans.clear();tot = 0;
}
void update(int &cur, int ori, int l, int r, int pos)
{cur = ++tot;T[cur] = T[ori];++T[cur].cnt;if (l == r)return ;int mid = MID(l, r);if (pos <= mid)update(T[cur].lson, T[ori].lson, l, mid, pos);elseupdate(T[cur].rson, T[ori].rson, mid + 1, r, pos);
}
int query(int S, int E, int l, int r, int ql, int qr)
{int ret = 0;if (ql <= l && r <= qr)ret = T[E].cnt - T[S].cnt;else{int mid = MID(l, r);if (ql <= mid)ret += query(T[S].lson, T[E].lson, l, mid, ql, qr);if (qr > mid)ret += query(T[S].rson, T[E].rson, mid + 1, r, ql, qr);}return ret;
}
int main(void)
{int n, i;while (~scanf("%d", &n)){init();for (i = 1; i <= n; ++i){scanf("%d", &arr[i]);vec.push_back(arr[i]);}sort(vec.begin(), vec.end());vec.erase(unique(vec.begin(), vec.end()), vec.end());for (i = 1; i <= n; ++i)arr[i] = lower_bound(vec.begin(), vec.end(), arr[i]) - vec.begin() + 1;for (i = 1; i <= n; ++i)update(root[i], root[i - 1], 1, 100000, arr[i]);for (i = 1; i <= n; ++i){bool flag = true;if (i - 1 >= 0 && arr[i] + 1 <= 100000)flag &= (query(root[0], root[i - 1],  1, 100000, arr[i] + 1, 100000) == 0); //查询左边是否有大于key的数if (flag && arr[i] - 1 >= 1)flag &= (query(root[i], root[n], 1, 100000, 1, arr[i] - 1) == 0); //查询右边是否有小于key的数if (flag)ans.push_back(vec[arr[i] - 1]);}int sz = ans.size();printf("%d\n", sz);sort(ans.begin(), ans.end());for (i = 0; i < sz; ++i)printf("%d%s", ans[i], i == sz - 1 ? "\n" : " ");if (!sz)putchar('\n');}return 0;
}

转载于:https://www.cnblogs.com/Blackops/p/6244062.html

PAT (Basic Level) Practise 1045 快速排序(离散化+主席树区间内的区间求和)相关推荐

  1. PAT (Basic Level) Practise (中文)-1025. 反转链表 (25)

    PAT (Basic Level) Practise (中文)-1025. 反转链表 (25)   http://www.patest.cn/contests/pat-b-practise/1025 ...

  2. PAT (Basic Level) Practise (中文)-1034. 有理数四则运算(20)

    PAT (Basic Level) Practise (中文)-1034. 有理数四则运算(20)  http://www.patest.cn/contests/pat-b-practise/1034 ...

  3. 卡拉兹(Callatz)猜想,PAT(Basic Level) Practise NO.1001

    PAT(Basic Level) Practise NO.1001 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半. 这样 ...

  4. PAT乙级真题全集-PAT (Basic Level) Practise (中文)

    1001. 害死人不偿命的(3n+1)猜想 (15) 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去, ...

  5. PAT (Basic Level) Practise 1040 有几个PAT(DP)

    1040. 有几个PAT(25) 时间限制 120 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CAO, Peng 字符串APPAPT中包含了两个单 ...

  6. PAT (Basic Level) Practise:1012. 数字分类

    [题目链接] 给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和: A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3- ...

  7. PAT (Basic Level) Practise:1017. A除以B

    [题目链接] 本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数.你需要输出商数Q和余数R,使得A = B * Q + R成立. 输入格式: 输入在1行中依次给出A和B,中间以1空格 ...

  8. PAT (Basic Level) Practise - 继续(3n+1)猜想

    题目链接:https://www.patest.cn/submissions/4414905 1005. 继续(3n+1)猜想 (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限 ...

  9. PAT (Basic Level) Practise:1037. 在霍格沃茨找零钱

    [题目链接] 如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 -- 就如海格告诉哈利的:"十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西 ...

最新文章

  1. tar命令-压缩,解压缩文件
  2. 数据挖掘分析的必要性
  3. python PyQt5 QComboBox类(下拉列表框、组合下拉框)
  4. IEEE作者中心!解决你的选刊,模板,选题,写做的一系列困难!!!拿走不谢!!!
  5. python用变量输出abcd_python中星号变量的几种特殊用法
  6. 【图像处理】Qt+OpenCV自制mini软件——图像二值化器
  7. linux系统的空间满的问题
  8. 线程同步(互斥锁与信号量的作用与区别)
  9. python查看数据库存在表_python sqlite3查看数据库所有表(table)
  10. linux汉诺塔实验报告,汉诺塔问题实验报告
  11. 微信自动回复 html 点击文字,【微信开发】公众号自动回复文字和图文链接(示例代码)...
  12. 如何把pdf拆分成一页一页的图片?
  13. 完美世界年营收85亿:同比降17% 影视业务整体产生亏损2亿
  14. MAR位数反映存储单元的个数笔记
  15. 关于数学计算机手抄报简单的,最简单的数学手抄报图片大全
  16. 一文带你深入理解Redis中的底层数据结构,再也不怕不懂数据类型的底层了
  17. 【图解】连狗子都能看懂的Python基础总结(二)什么是库、包、模块?
  18. 【语音之家】AI产业沙龙—语音技术在贝壳的应用
  19. linux yum使用管理详细使用转载的
  20. 为什么Python这么火

热门文章

  1. Android NDK 使用第三方静态库(转)
  2. 充实你的素材库!10款免费的 PSD 素材下载
  3. Luogu P3975 [TJOI2015]弦论
  4. 将网桥的配置写进去/etc/sysconfig/network-scripts/ifcfg-xxx
  5. 经常使用的 WEB server
  6. Android属性动画进阶用法
  7. android 弹起键盘把ui顶上去的解决办法
  8. linux 程序包管理5 编译安装
  9. Crystal 语法概述[转]
  10. PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilder