目录
逆序对的数量 (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;
}