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


    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
    ", sz);
    		sort(ans.begin(), ans.end());
    		for (i = 0; i < sz; ++i)
    			printf("%d%s", ans[i], i == sz - 1 ? "
    " : " ");
    		if (!sz)
    			putchar('
    ');
    	}
    	return 0;
    }
  • 相关阅读:
    hadoop 环境配置
    批量生成不同尺寸的图片
    如何生成publish windows app 用到的 pfx 文件
    MVC项目用Windsor注入
    UWP textbox 只能输入数字
    power shell upload file to azure storage
    Checkbox can't checked
    安装部署 Goaccess
    阿里云OSS的Bucket容量大小采集
    1. Nagios和 NagiosQL安装及配置
  • 原文地址:https://www.cnblogs.com/Blackops/p/6244062.html
Copyright © 2020-2023  润新知