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);
else
update(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;
}

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

  1. PAT (Basic Level) Practise (中文)-1039. 到底买不买(20)

    PAT (Basic Level) Practise (中文)-1039. 到底买不买(20) http://www.patest.cn/contests/pat-b-practise/1039 小红 ...

  2. PAT (Basic Level) Practise (中文)- 1022. D进制的A+B (20)

    PAT (Basic Level) Practise (中文)-  1022. D进制的A+B (20)  http://www.patest.cn/contests/pat-b-practise/1 ...

  3. PAT (Basic Level) Practise (中文)- 1024. 科学计数法 (20)

    PAT (Basic Level) Practise (中文)- 1024. 科学计数法 (20) http://www.patest.cn/contests/pat-b-practise/1024 ...

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

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

  5. PAT (Basic Level) Practise (中文)- 1026. 程序运行时间(15)

    PAT (Basic Level) Practise (中文)- 1026. 程序运行时间(15)    http://www.patest.cn/contests/pat-b-practise/10 ...

  6. PAT (Basic Level) Practise (中文)-1027. 打印沙漏(20)

    PAT (Basic Level) Practise (中文)-1027. 打印沙漏(20)  http://www.patest.cn/contests/pat-b-practise/1027 本题 ...

  7. PAT (Basic Level) Practise (中文)-1028. 人口普查(20)

    PAT (Basic Level) Practise (中文)-1028. 人口普查(20)   http://www.patest.cn/contests/pat-b-practise/1028 某 ...

  8. PAT (Basic Level) Practise (中文)-1029. 旧键盘(20)

    PAT (Basic Level) Practise (中文)-1029. 旧键盘(20) http://www.patest.cn/contests/pat-b-practise/1029 旧键盘上 ...

  9. PAT (Basic Level) Practise (中文)-1030. 完美数列(25)

    PAT (Basic Level) Practise (中文)-1030. 完美数列(25)   http://www.patest.cn/contests/pat-b-practise/1030 给 ...

随机推荐

  1. 【转】Java开发中JDBC连接数据库代码和步骤总结

    (转自:http://www.cnblogs.com/hongten/archive/2011/03/29/1998311.html) JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含7个 ...

  2. scala安装

    一:在官网下载相应的版本http://www.scala-lang.org/download/2.10.6.html 二,在linux中解压下载下来的scala包   三:配置环境变量 export ...

  3. Python爬虫Scrapy框架入门(1)

    也许是很少接触python的原因,我觉得是Scrapy框架和以往Java框架很不一样:它真的是个框架. 从表层来看,与Java框架引入jar包.配置xml或.property文件不同,Scrapy的模 ...

  4. ca 自签名证书 并实现HAProxy https功能

    mkdir /etc/ssl/xip.io [root@ha02 haproxy-]# openssl genrsa - Generating RSA bit long modulus ....... ...

  5. python多线程编程

    Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join( ...

  6. [MongoDB]安装MongoDB

    汇总: 1. [MongoDB]安装MongoDB2. [MongoDB]Mongo基本使用:3. [MongoDB]MongoDB的优缺点及与关系型数据库的比较4. [MongoDB]MongoDB ...

  7. Linux第01天

    Linux第01天 1.虚拟机安装linux(centos 32bit) 1.1 虚拟机安装前置工作的准备,如内存.硬盘.CPU分配.镜像下载等 1.2 安装方式(图形界面或者命令行 推荐图形界面即直 ...

  8. android tab选项卡的使用

    项目做完了,写写博客,在项目中遇到的一些问题,或者是自己觉得很不错的东西.这一篇主要是想和大家分享一下我在项目中封装的一个东西,就是tab选项卡.先看看效果图: 我在网上看了很多有关选项卡的demo, ...

  9. JSON.parse()和JSON.stringify()区别

    parse用于从一个字符串中解析出json对象,如: var str = '{"name":"huangxiaojian","age":&q ...

  10. 廖雪峰js教程笔记14 file文件操作

    在HTML表单中,可以上传文件的唯一控件就是<input type="file">. 注意:当一个表单包含<input type="file" ...