Counter Strike HDU 2443 逆序对数

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2443

这个题目尝试了很多种方法都过不去,上网查了一下网友们的的思路,竟然和逆序对数有关系!!

题目大意:

有n个士兵,他们都有各自的分数,有一项任务需要完成,为了能够确保合作更默契,他们的分数要差不多,所以有一个水平控制即平均数,所选的一组士兵的平均成绩必须大于该平均数。

问一共能选出多少组士兵能够完成该项任务?

思路:

求逆序对数。归并排序可以用来求逆序对数,这个没毛病。

代码如下:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 void combine_sortd_list(int* to, int* sub1, int sz1, int* sub2, int sz2);
 5 void merge_sort(int* lst, int sz);
 6 const int MAX = 1e5 + 5;
 7 int arr[MAX];
 8 long long int ans;
 9 int main()
10 {
11     int Group, N, A;
12     cin >> Group;
13     while (Group--)
14     {
15         memset(arr, 0, sizeof arr);
16         cin >> N >> A;
17         for (int j, i = N-1; i >=0; --i)
18         {
19             cin >> j;
20             arr[i] = j - A + arr[i + 1];
21         }
22         ans = 0;
23         merge_sort(arr, N + 1);             //归并求逆序数
24         cout << ans << endl;
25     }
26 }
27 void merge_sort(int* lst, int sz)
28 {
29     static int tmp[MAX];
30     if (sz <= 1)return;
31     int* l = lst;
32     int lsz = (sz + 1) / 2;
33     int* r = l + lsz;
34     int rsz = sz / 2;
35     merge_sort(l, lsz);
36     merge_sort(r, rsz);
37     combine_sortd_list(tmp, l, lsz, r, rsz);
38     for (int i = 0; i < sz; ++i)lst[i] = tmp[i];
39 }
40 void combine_sortd_list(int*to, int* sub1, int sz1, int* sub2, int sz2)
41 {
42     int i = 0, j = 0, k = 0;
43     while (i < sz1&&j < sz2)
44         if (sub1[i] <= sub2[j])to[k++] = sub1[i++];
45         else
46         {
47             ans += sz1 - i;
48             to[k++] = sub2[j++];
49         }
50     while (i < sz1)to[k++] = sub1[i++];
51     while (j < sz2)to[k++] = sub2[j++];
52 }

由公式推导解析题目意图:http://blog.csdn.net/scorpiocj/article/details/6227528

感谢您的阅读,生活愉快~

原文地址:https://www.cnblogs.com/lv-anchoret/p/8461070.html

时间: 2024-08-02 00:13:24

Counter Strike HDU 2443 逆序对数的相关文章

POJ 2299 Ultra-QuickSort (树状数组or 归并排序分治求逆序对数)

题目大意就是说帮你给一些(n个)乱序的数,让你求冒泡排序需要交换数的次数(n<=500000) 显然不能直接模拟冒泡排序,其实交换的次数就是序列的逆序对数. 由于数据范围是 0 ≤ a[i] ≤ 999,999,999所以先要离散化,然后用合适的数据结果求出逆序 可以用线段树一步一步添加a[i],每添加前查询前面添加比它的大的有多少个就可以了. 也可用树状数组,由于树状数组求的是(1...x)的数量和所以每次添加前查询i-sum(a[i])即可 树状数组: //5620K 688MS #incl

POJ 2299 Ultra-QuickSort(归并排序求逆序对数)

题目地址:POJ 2299 今天下午的多校看来没有白做...实在做不出题闲着无聊看小白鼠学会了个归并排序.哈哈. 归并排序简单地说其实就是先分成一个二叉树直至单个,然后依次从最底层不断进行合并,逆序对数就是在合并的过程中,加入后面的那段中到了比他大的时候,那后面的那些就都是比他大的,都是逆序对数,所以直接加上即可.网上资料很多,就不细说了..用了分治的思想. 自己根据理解写的代码,考虑的太不全面了..又调了好长时间... 代码如下: #include <algorithm> #include

POJ 1840 Brainman(逆序对数)

题目链接:http://poj.org/problem?id=1804 题意:给定一个序列a[],每次只允许交换相邻两个数,最少要交换多少次才能把它变成非递降序列. 思路:题目就是要求逆序对数,我们知道,求逆序对最典型的方法就是树状数组,但是还有一种方法就是Merge_sort(),即归并排序.实际上归并排序的交换次数就是这个数组的逆序对个数,归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来.在合并的过程中(设l<=i<=mid

POJ 2299 Ultra-QuickSort (求序列的逆序对数)

题意:废话了一大堆就是要你去求一个序列冒泡排序所需的交换的次数. 思路:实际上是要你去求一个序列的逆序队数 看案例: 9 1 0 5 4 9后面比它小的的数有4个 1后面有1个 0后面没有 5后面1个 4后面没有 所以结果为4+1+0+1+0=6 所以逆序对的定义如果不清楚可以自己总结了 这道题说白了就是要你用归并排序求逆序对数. 下面是搜到某牛给的逆序对数的方法: 假设回溯到某一步,后面的两部分已经排好序(就是说当前需要归并的两个部分都是分别有序的),假设这两个序列为 序列a1:2 3 5 9

Time Limit Exceeded 求逆序对数。

/** 题目:Time Limit Exceeded 链接:https://oj.ejq.me/problem/28 题意:求逆序对数. 思路:树状数组求逆序对数.维护前面有多少个<=当前数的数的个数. */ #include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn = 1e6+10; const int mod = 1e9+7; ll c[maxn]; int flag[maxn]

ACM:归并排序,以及利用归并排序思想求解逆序对数!

(一)归并排序 分析: (1)划分问题:把序列分成元素个数尽量相等的两半. (2)递归求解:把两半元素分别排序. (3)合并问题:把两个有序表合并成一个.(每次只需要把两个序列的最小元素加以比较,删除其中的较小元素并加入合并后的新表) #include <iostream> using namespace std; const int MAXN = 1000; int A[MAXN], T[MAXN]; void merge_sort(int *A, int x, int y, int *T)

zoj 3157 Weapon 线段树求逆序对数

题目链接:http://www.icpc.moe/onlinejudge/showProblem.do?problemId=3128 题意:平面上有n条直线,给出l, r,求出这些直线的交点横坐标在(l, r)范围内的个数. 思路: 首先求出每条直线与直线x = l和直线x = r的交点,如下图. 因为题目要求区间(l, r)是开区间,所以为了避免交点的横坐标刚好是l或者r的情况,可以先把l加上一个很小的值,r减去一个很小的值,如图中的灰线. 然后求出各条直线与两条灰线的交点,首先按与l的交点的

微软面试题:求一个序列的逆序对数

双层循环排序,时间为O(n2) 归并排序时间为O(nlog(n)) #include<iostream> #include<cstdio> #include<vector> using namespace std; int cnt=0; void merge(vector<int> & nums,int left,int mid,int right); void mergesort(vector<int> & nums,int s

算法设计《分治法》归并排序(三)实例分析之逆序对数

问题定义: 假设A[1...n]是一个有n个不同数的数组.若i<j且A[i]>A[j]则称(A[i], A[j])为数组A的一个逆序对. 例如数组<2, 3, 8, 6, 1>有(2, 1),(3, 1),(8, 6),(8, 1)和(6,1)5个逆序对. 对于这个问题,直观上进行求解的话,使用暴力求解的方式的话,对于每个数num,都遍历数组中num后的所有数的话,则时间复杂度为O(n^2). 实现代码如下: 另一种方式,便是使用分治法,首先将整个数组分成两部分,然后,分别求解两个