sdut pta排序

9 篇文章 1 订阅

7-1 统计工龄

给定公司N名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。

输入格式:

输入首先给出正整数N(≤105),即员工总人数;随后给出N个整数,即每个员工的工龄,范围在[0, 50]。

输出格式:

按工龄的递增顺序输出每个工龄的员工个数,格式为:“工龄:人数”。每项占一行。如果人数为0则不输出该项。

输入样例:

8
10 2 0 5 7 2 5 2

输出样例:

0:1
2:3
5:2
7:1
10:1
#include<bits/stdc++.h>
using namespace std;
const int N = 55;
int cnt[N];
int main()
{
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		int year;
		cin >> year;
		cnt[year]++;
	}
	for(int i = 0; i <= 50; i++){
		if(cnt[i]){
			cout << i << ":" << cnt[i] << endl;
		}
	}
	return 0;
}

 

7-2 寻找大富翁

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

输入格式:

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

输出格式:

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

输入样例:

8 3
8 12 7 3 20 9 5 18

输出样例:

20 18 12
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
long long int a[N];
int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 0; i < n; i++){
        cin >> a[i];
    }
    sort(a, a + n);
    if(m > n){
        m = n;
    }
    for(int i = n - 1; i >= n - m; i--){
        printf("%lld%c", a[i], i == n - m ? '\n' : ' ');
    }
    return 0;
}

 

7-3 点赞狂魔

微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这种人就被称为“点赞狂魔”。他们点赞的标签非常分散,无法体现出明显的特性。本题就要求你写个程序,通过统计每个人点赞的不同标签的数量,找出前3名点赞狂魔。

输入格式:

输入在第一行给出一个正整数N(≤100),是待统计的用户数。随后N行,每行列出一位用户的点赞标签。格式为“Name K F1​⋯FK​”,其中Name是不超过8个英文小写字母的非空用户名,1≤K≤1000,Fi​(i=1,⋯,K)是特性标签的编号,我们将所有特性标签从 1 到 107 编号。数字间以空格分隔。

输出格式:

统计每个人点赞的不同标签的数量,找出数量最大的前3名,在一行中顺序输出他们的用户名,其间以1个空格分隔,且行末不得有多余空格。如果有并列,则输出标签出现次数平均值最小的那个,题目保证这样的用户没有并列。若不足3人,则用-补齐缺失,例如mike jenny -就表示只有2人。

输入样例:

5
bob 11 101 102 103 104 105 106 107 108 108 107 107
peter 8 1 2 3 4 3 2 5 1
chris 12 1 2 3 4 5 6 7 8 9 1 2 3
john 10 8 7 6 5 4 3 2 1 7 5
jack 9 6 7 8 9 10 11 12 13 14

输出样例:

jack chris john
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
set<int>s;
struct node{
    string name;
    int sum;
    int cnt;
}like[N];
bool cmp(node a, node b){
    if(a.cnt != b.cnt) return a.cnt > b.cnt;
    else return a.sum < b.sum;
}
int main()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> like[i].name >> like[i].sum;
        for(int j = 0; j < like[i].sum; j++){
            int x;
            cin >> x;
            s.insert(x);
        }
        like[i].cnt = s.size();
        s.clear();
    }
    sort(like, like + n, cmp);
    int i = 0; 
    for(; i < 3 && i < n; i++){
        if(i == 0) cout << like[i].name;
        else cout << ' ' << like[i].name;
    }
    for(; i < 3; i++){
        cout << ' ' << '-';
    }
}

7-4 插入排序还是归并排序

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。

输入样例 1:

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

输出样例 1:

Insertion Sort
1 2 3 5 7 8 9 4 6 0

输入样例 2:

10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

输出样例 2:

Merge Sort
1 2 3 8 4 5 7 9 0 6
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N], ans[N];
int main()
{
    int n, range = 2;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> a[i];
    }
    for(int j = 0; j < n; j++){
        cin >> ans[j];
    }
    int i, j;
    for(i = 1; i < n; i++){
        if(ans[i] < ans[i-1]){
            break;
        }
    }
    for(j = i; j < n; j++){
        if(ans[j] != a[j]){
            break;
        }
    }
    if(j < n){
        cout << "Merge Sort" << endl;
        while(1){
            for(i = 0; i < n; i++){
                if(ans[i] != a[i]){
                    break;
                }
            }
            for(j = 0; j < n / range; j++){
                sort(a+j*range, a+(j+1)*range);
            }
            sort(a+n/range*range, a+n);
            if(i == n) break;
            range *= 2;
        }
    }
    else{
        cout << "Insertion Sort" << endl;
        sort(a, a+i+1);
    }
    for(i = 0; i < n; i++){
        if(i == 0) cout << a[i];
        else cout << ' ' << a[i];
    }
    return 0;
}

7-5 插入排序还是堆排序

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

堆排序也是将输入分为有序和无序两部分,迭代地从无序部分找出最大元素放入有序部分。它利用了大根堆的堆顶元素最大这一特征,使得在当前无序区中选取最大元素变得简单。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第 1 行中输出Insertion Sort表示插入排序、或Heap Sort表示堆排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。

输入样例 1:

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

输出样例 1:

Insertion Sort
1 2 3 5 7 8 9 4 6 0

输入样例 2:

10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9

输出样例 2:

Heap Sort
5 4 3 1 0 2 6 7 8 9
#include<bits/stdc++.h>
#define INF 99999999
using namespace std;
int n; 
int before[110];
int after[110];
int sorted[110];

int main(){
	scanf("%d",&n); 
	for(int i=0;i<n;i++) {
		scanf("%d",&before[i]);
		sorted[i]=before[i];
	}
	for(int i=0;i<n;i++) scanf("%d",&after[i]);
	int count1=0,count2=0;
	for(int i=0;i<=n;i++){
		if(after[i]>after[i+1]){
			count1=i;
			break;
		}
	}
	for(int i=count1+1;i<n;i++){
		if(before[i]==after[i]){
			count2++;
		}else break;
	}
	if(count2+count1+1==n){
		printf("Insertion Sort\n");
		sort(after,after+count1+2);
		for(int i=0;i<n-1;i++)
			printf("%d ",after[i]); 
		printf("%d\n",after[n-1]);
	}
	else{
		printf("Heap Sort\n");
		int a=n-1;
		while(after[a]>after[0]) a--;
		swap(after[a],after[0]);
		int low=0,high=1;
		while(high<a){
			if(high+1<a&&after[high]<after[high+1])high++;
			if(after[low]>after[high])break;
			swap(after[low],after[high]);
			low=high;high=low*2+1;
		}
		for(int i=0;i<n-1;i++)
			printf("%d ",after[i]); 
		printf("%d\n",after[n-1]);
	}
	return 0;
}

 

7-6 逆序对

求逆序对。

输入格式:

第一行是一个整数n,(n<=1000,000)表示输入序列的长度,接下来一行是n个整数(每个数的绝对值小于109)。

输出格式:

一个数,表示逆序对个数(逆序即任意一对数前面的数比后面的数大即为一对逆序对)。

输入样例:

10
1 3 5 7 9 8 4 2 6 10

输出样例:

逆序对对数可能很大,计数器要用long long:

14

说明:样例中如1和3不是逆序对,而3和2是1对逆序对,例子中共有14对逆序对。题目中可能有某些数字出现多次的情况。

#include<bits/stdc++.h>
using namespace std;
const int  N = 1e6 + 10;
typedef long long ll;
ll cnt;
int a[N], c[N];
void merge(int s, int e){
    if(s == e) return ;
    int mid = s + e >> 1;
    merge(s, mid);
    merge(mid + 1, e);
    int i = s, j = mid + 1, k = s;
    while(i <= mid && j <= e){
        if(a[i] <= a[j]){
            c[k++] = a[i++];
        }
        else{
            c[k++] = a[j++];
            cnt += mid -i + 1;
        }
    }
    while(i <= mid) c[k++] = a[i++];
    while(j <= e) c[k++] = a[j++];
    for(int i = s; i <= e; i++){
        a[i] = c[i];
    }
}
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    merge(1, n);
    cout << cnt << endl;
    return 0;
}

7-7 堆排序

给定一个整数序列,请按非递减序输出采用堆排序的各趟排序后的结果。

输入格式:

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

输出格式:

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

输入样例:

4
8 7 2 1

输出样例:

7 1 2 8
2 1 7 8
1 2 7 8
#include<bits/stdc++.h>
using namespace std;

void HeapAdjust(int* a, int i, int n)  
{
    int lchild = 2 * i;       
    int rchild = 2 * i + 1;  
    int max = i;         
    if (i <= n / 2) {      
        if (lchild <= n && a[lchild] > a[max])
            max = lchild;
        if (rchild <= n && a[rchild] > a[max])
            max = rchild;
        if (max != i) {
            swap(a[i], a[max]);
            HeapAdjust(a, max, n);  
        }
    }
}
void BuildHeap(int* a, int n)  
{
    for (int i = n / 2; i >= 1; i--){  
        HeapAdjust(a, i, n);
    }
}
 
void HeapSort(int* a, int n)
{
    BuildHeap(a, n);
    for (int i = n; i > 1; i--){
        swap(a[1], a[i]); 
        HeapAdjust(a, 1, i - 1); 
        for (int j = 1; j <= n; j++){
            if (j == 1)
                cout << a[j];
            else
                cout << " " << a[j];
        }
        cout << endl;
    }
}
int main()
{
    int a[100], n;
    while (~scanf("%d", &n)){
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        HeapSort(a, n);
    }
    return 0;
}

7-8 石子合并

由n堆石子排成一排,其编号为1,2,3……,n。每堆石子有一定的质量mi(mi<=1000),现在要将这n堆石子合并成一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,由于合并顺序的不同,导致合并成一堆石子的总代价也不同,请求出最少的代价将所有石子合并为一堆。

输入格式:

第一行输入n。
第二行输入n个mi。

输出格式:

输出一个整数,表示石子合并的最小代价。

输入样例:

4
2 5 3 1

输出样例:

22
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N = 210;
int a[N], sum[N], f[N][N];
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        sum[i] = sum[i-1] + a[i];
    }
    memset(f, INF, sizeof(f));
    for(int len = 1; len <= n; len++){
        for(int i = 1; i + len - 1 <= n; i++){
            int j = i + len - 1;
            if(len == 1) f[i][j] = 0;
            else{
                for(int k = i; k < j; k++){
                    f[i][j]=min(f[i][j], f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
                }
            }
        }
    }
    cout << f[1][n] << endl;
    return 0;
}

7-9 第k小

有n个数,求第k小的数。例如在数:{1 3 5 7 9 8 4 2 6 10}中,第3小的数是3 。

输入格式:

第一行输入两个数,n和k(n<=1000000),分别表示总的n个数和求第k小的数。第二行输入n个数( 最大数<10^7)。

输出格式:

一个数,表示第k小的数。

输入样例:

在这里给出一组输入。例如:

10 3
1 3 5 7 9 8 4 2 6 10

输出样例:

在这里给出相应的输出。例如:

3
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    for(int i = 0; i < n; i++){
        scanf("%d", &a[i]);
    }
    sort(a, a + n);
    printf("%d", a[k-1]);
}

7-10 快速排序的过程

给定n个整型元素,利用快速排序算法对其进行非递减排序,请输出每一趟Partition的结果。每次选择所处理的区间的第一个元素作为基准元素。

输入格式:

输入为两行,第一行为一个整数n(1<n≤1000),表示元素个数。第二行为n个空格间隔的整数,表示待排序的元素。

输出格式:

输出为若干行,每行依次输出Partition后的结果,每个元素后一个空格。

输入样例:

5
4 5 3 2 1

输出样例:

2 1 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
#include<bits/stdc++.h>
using namespace std;
int n;
void print(int a[]){
    for(int i = 0; i < n; i++){
        cout << a[i] <<' ';
    }
    cout << endl;
}
void Quick_Sort(int a[], int l, int r){
    if(l > r) return ;
    int i = l, j = r, t = a[l];
    while(i < j){
        while(a[j] >= t && i < j){
            j--;
        }
        while(a[i] <= t && i < j){
            i++;
        }
        if(i < j){
            swap(a[i], a[j]);
        }
        
    }
    swap(a[l], a[i]);
    print(a);
    Quick_Sort(a, l, i - 1);
    Quick_Sort(a, i+1, r);
}
const int N = 1e3 + 10;
int a[N];
int main(){
    
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> a[i];
    }
    Quick_Sort(a, 0, n - 1);
    return 0;
}

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值