第四次机测

目录

逆序对的数量 (15 分)

输入格式:

输出格式:

输入样例:

输出样例:

寻找大富翁 (15 分)

输入格式:

输出格式:

快速排序 (15 分)

输入格式:

输出格式:

两个有序序列的中位数 (20 分)

输入格式:

输出格式:

单身狗 (15 分)

输入格式:

输出格式:

输入样例:

输出样例:

中序遍历树并判断是否为二叉搜索树 (20 分)

输入格式:


 

逆序对的数量 (15 分)

知识点:归并排序

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。

逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。

输入格式:

第一行包含整数 n(1≤n≤100000),表示数列的长度。

第二行包含 n 个整数,表示整个数列,数列中的元素的取值范围 [1~10^9]。

输出格式:

请在这里描述输出格式。例如:对每一组输入,在一行中输出A+B的值。

输入样例:

6
2 3 4 5 6 1

结尾无空行

输出样例:

5
#include<bits/stdc++.h>
const int M=100005;
using namespace std;
int a[M],d[M],t[M],n;
int lowbit(int x)
{
	return x&-x;
}
int add(int x)
{
	while(x<=n)
	{
		t[x]++;
		x+=lowbit(x);
	}
}
int sum(int x)
{
	int res=0;
	while(x>=1)
	{
		res+=t[x];
		x-=lowbit(x);
	}
	return res;
}
bool cmp(int x,int y)
{
	if(a[x]==a[y]) return x>y;
	return a[x]>a[y];
}
int main()
{
	long long ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i],d[i]=i;
	sort(d+1,d+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		add(d[i]);
		ans+=sum(d[i]-1);
	}
	cout<<ans;
	return 0;
}

 

寻找大富翁 (15 分)

胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。

输入格式:

输入首先给出两个正整数N(≤106)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。

输出格式:

在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int main()
{
    long long int a[maxn];
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    m>n?m=n:m=m;
    for(int i=n-1;i>n-m;i--)
        printf("%lld ",a[i]);
    cout<<a[n-m]<<endl;
}

 

快速排序 (15 分)

给定一个整数序列,请按非递减序输出采用快速排序(递归法)的各趟排序后的结果。注意:每趟排序以排序区间的首元素为枢轴(支点)。

输入格式:

测试数据有多组,处理到文件尾。每组测试数据第一行输入一个整数n(1≤n≤100),第二行输入n个整数。

输出格式:

对于每组测试,输出若干行,每行是一趟排序后的结果,每行的每两个数据之间留一个空格。

#include<bits/stdc++.h>
using namespace std;
#define N 100001
int a[N];
int n;
void f(int a[],int l,int r)
{
    int x=a[l],i=l,j=r;
    if(i>=j)
        return ;
    while(i<j)
    {
        while(i<j&&a[j]>=x)
            j--;
        a[i]=a[j];
        while(i<j&&a[i]<=x)
            i++;
        a[j]=a[i];
    }
    a[i]=x;
    cout<<a[0];
    for(int i=1;i<n;i++)
    {
        cout<<" "<<a[i];
    }
    cout<<endl;
    f(a,l,i-1);
    f(a,i+1,r);
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        cin>>a[i];
            f(a,0,n-1);
    }
}

 

两个有序序列的中位数 (20 分)

已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0​,A1​,⋯,AN−1​的中位数指A(N−1)/2​的值,即第⌊(N+1)/2⌋个数(A0​为第1个数)。

输入格式:

输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。

输出格式:

在一行中输出两个输入序列的并集序列的中位数。

#include<bits/stdc++.h>
using namespace std;
vector<int>v;
int main()
{
    int n,m;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>m;
        v.push_back(m);
    }
    for(int i=0;i<n;i++)
    {
        cin>>m;
        v.push_back(m);
    }
    sort(v.begin(),v.end());
    cout<<v[(2*n-1)/2];
}

 

单身狗 (15 分)

“单身狗”是中文对于单身人士的一种爱称。本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱。

输入格式:

输入第一行给出一个正整数 N(≤50000),是已知夫妻/伴侣的对数;随后 N 行,每行给出一对夫妻/伴侣——为方便起见,每人对应一个 ID 号,为 5 位数字(从 00000 到 99999),ID 间以空格分隔;之后给出一个正整数 M(≤10000),为参加派对的总人数;随后一行给出这 M 位客人的 ID,以空格分隔。题目保证无人重婚或脚踩两条船。

输出格式:

首先第一行输出落单客人的总人数;随后第二行按 ID 递增顺序列出落单的客人。ID 间用 1 个空格分隔,行的首尾不得有多余空格。

输入样例:

3
11111 22222
33333 44444
55555 66666
7
55555 44444 10000 88888 22222 11111 23333

结尾无空行

输出样例:

5
10000 23333 44444 55555 88888

结尾无空行

#include<bits/stdc++.h>
#define N 500005
#define inf 0x3f3f3f3f
using namespace std;
int id[N];

int main(){
    map<int,int>ma,List,dog;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        int a,b;
        cin>>a>>b;
        ma[a]=b;
        ma[b]=a;
    }
    int m;
    cin>>m;
    int num=0;
    for(int i=0;i<m;i++){
        int a;
        cin>>a;
        List[a]=1;
        if(!ma.count(a)||!List.count(ma[a]))
            dog[a]==1;
        else{
            if(dog.count(ma[a]))
                dog.erase(ma[a]);
        }
    }
    cout<<dog.size()<<endl;
    map<int,int>::iterator it;
    for(it=dog.begin();it!=dog.end();it++){
        if(it==dog.begin())
            printf("%05d",it->first);
        else
            printf(" %05d",it->first);
    }
    return 0;
}

 

中序遍历树并判断是否为二叉搜索树 (20 分)

对给定的有N个节点(N>=0)的二叉树,给出中序遍历序列,并判断是否为二叉搜索树。

题目保证二叉树不超过200个节点,节点数值在整型int范围内且各不相同。

输入格式:

第一行是一个非负整数N,表示有N个节点

第二行是一个整数k,是树根的元素值

接下来有N-1行,每行是一个新节点,格式为 r d e 三个整数,

r表示该节点的父节点元素值(保证父节点存在);d是方向,0表示该节点为父节点的左儿子,1表示右儿子;e是该节点的元素值

#include<bits/stdc++.h>
#define N 500005
#define inf 0x3f3f3f3f
using namespace std;
map<int,int>lc,rc;
int n,s;
void zhong(int s)
{
    if(lc.count(s)==1)
        zhong(lc[s]);
    cout<<s<<endl;
    if(rc.count(s)==1)
        zhong(rc[s]);
}
int main()
{
    cin>>n;
    if(n==0)
    {
        cout<<"Yes"<<endl;
        return 0;
    }
    cin>>s;
    int flag=0;
    for(int i=0;i<n-1;i++)
    {
        int r,d,e;
        cin>>r>>d>>e;
        if(d==0)
        {
            if(e>r) flag=1;
            lc[r]=e;
        }
        else
        {
            if(e<r) flag=1;
            rc[r]=e;
        }
    }
    zhong(s);
    if(flag==1)
        cout<<"No"<<endl;
    else
        cout<<"Yes"<<endl;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值