当前位置: 首页 > wzjs >正文

网站公司模板推广资源网

网站公司模板,推广资源网,手机网站建设的目的,东莞黄江做网站公司目录 前言 超快速排序 分析 代码 小朋友排队 分析 代码 鱼塘钓鱼 分析 代码 前言 本来计划今天写五道题的,结果计划赶不上变化,谁能告诉我我的时间都去哪了。。。 今天给大家带来三道题目,两道逆序对问题,分别用归并排…

目录

前言

超快速排序

分析

代码

小朋友排队

分析

代码

鱼塘钓鱼

分析

代码


前言

本来计划今天写五道题的,结果计划赶不上变化,谁能告诉我我的时间都去哪了。。。

今天给大家带来三道题目,两道逆序对问题,分别用归并排序和树状数组求解,一道多路归并。


超快速排序


分析

看完题目首先想到的是冒泡排序,但是显然冒泡排序不属于“超快速排序”。

但是既然题目的最终目的是排序,那就肯定离不开排序算法。

学过线性代数的同学都知道,有一个东西叫做逆序数,指的就是一组排列中逆序对的个数

逆序对能不能和本题的“交换次数”联系起来呢?主播很明确的告诉你们,最优的方案的交换次数就是逆序数。

如何证明呢?这个简单。

我们知道,在一个排列中交换两个相邻的元素,造成的影响是逆序数加一或者减一。

而逆序数的含义可以视为,存在一种方案使得每次相邻的两个元素交换,都能使得逆序数减一。

接下来的问题就是证明这种方案存不存在,请观察我下面的式子:

2, 3, 1

可以观察到前两个数字是已排序的,若要让这个排列的逆序数归零只需要交换3和1, 2和1,最终排列就变成了这样

1, 2, 3

逆序数归零了,并且我们每次交换操作造成的影响都是逆序数减一

所以这种方案存在,具有充分性

观察原排列,可以发现原排列可以分为两部分,即:2, 3 | 1,而每一部分内部都是排序过的。

观察上方的排列,有没有想起一个排序算法,没错,那么算法就是归并排序

我们都知道归并排序是可以求逆序对数的,接下来主播就以自己的理解来解释归并排序为什么能够求逆序对数。

首先,我们将一个排列的逆序对视为一个集合S

随后,我们将排列分为两个区间,对集合进行划分,划分为区间内的逆序对和区间间的逆序对。

至于为什么可以划分很好证明,只需要证明三个子集没有包含关系即可,通过反证法很好证明。

那么整体的逆序对数就等于区间内的逆序对数 + 区间间的逆序对数。(容斥原理)

而归并排序就是利用这种思想,先消除区间内的逆序对,再消除区间间的逆序对,来达到计算逆序对数的效果。

而我们知道归并排序处理的每个区间都是排序后的两部分,所以根据上面的充分性,消除这样的区间的逆序对数的交换次数就是逆序对数。

所以问题就转化成了归并排序求逆序对数。


代码

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 500010;
int n;
int a[N],tmp[N];
LL merge_sort (int l,int r) {if (l == r) return 0;int mid = l + r >> 1;LL ans = merge_sort (l,mid) + merge_sort (mid + 1,r);int i = l,j = mid + 1,k = 0;while (i <= mid && j <= r) {if (a[i] <= a[j]) tmp[k++] = a[i++];else {tmp[k++] = a[j++];ans += mid - i + 1;}}while (i <= mid) tmp[k++] = a[i++];while (j <= r) tmp[k++] = a[j++];for (int i = l,j = 0;i <= r;i++,j++) a[i] = tmp[j];return ans;
}
int main () {while (cin >> n,n) {for (int i = 1;i <= n;i++) cin >> a[i];cout << merge_sort (1,n) << endl;}return 0;
}

小朋友排队


分析

前面我们证明了逆序对数就是至少交换次数,但是这道题有写不一样,我们需要统计交换双方需要交换的次数那显然就不只是逆序对数了。

主播刚开始以为答案就是逆序对数乘以二,可是后来发现这个想法是错误的,因为每个元素的逆序对数只能代表他“主动”与别人交换的次数,并不能代表这个元素交换的次数,观察下方案例。

3, 2, 1

通过观察可以发现要想排序可以发现1要交换两次,3要交换两次,2也需要交换两次。

要讲明白一个知识点,主播需要先引入一个概念:

顺序对(主播自己起的名字,也不知道对不对),与逆序对相反,不过区别是顺序对指的是在这个元素之后小于这个元素的个数。

反过来看,对于后面的元素来说,可以将顺序对拆分成n部分,而其中的每一部分就是对于该元素的一个逆序对。

而后面的元素要想消除自己的逆序对就一定要与当前元素进行交换,我们将这种行为视为消除该元素的顺序对。

这样就同时统计了每个元素主动交换和被动交换的所有情况,因为最开始行为是区间划分,所以也无需判重

主播这次是用树状数组实现,树状数组的写法很暴力,就是对每个数字统计在他前面且比他大的数字。


代码

// 树状数组求逆序对和顺序对
#include<iostream>
#include<cstring>
/*#define y second
#define x first*/
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 100010, P = 1000010;
int n;
int h[N];
int tree[P];
int st[N];
int lowbit(int x)
{return x & -x;
}void insert(int i, int x)
{if(i >= P) return;tree[i] += x;insert(i + lowbit(i), x);
}int find(int x)
{if(x == 0) return tree[0];return tree[x] + find(x - lowbit(x));
}int main()
{scanf("%d", &n);for(int i = 1; i <= n;h[i]++, i++) scanf("%d", h + i);for(int i = 1; i <= n; i++){st[i] += i - 1 - find(h[i]); //找大于当前数字的insert(h[i], 1);}memset(tree, 0, sizeof(tree));for(int i = n; i >= 1; i--){st[i] += find(h[i] - 1); // 小于当前数字的insert(h[i], 1);}LL l = 0;for(int i = 1; i <= n; i++)l += ((st[i] + 1) * (LL)st[i]) / 2;printf("%lld", l);return 0;
}

鱼塘钓鱼


分析

首先想到可以搜索,但是数据量很大,而且状态也不好表示,所以先排除搜索。

首先先观察整体,可以发现每次换鱼塘只会消耗时间而不会带来重复收益,所以贪心思路是至多到达一次此鱼塘,即:一条路走下去,不要反复横跳。(这种找最优解的题一般是先分析整体看有没有明显重复的部分,随后就可以根据这些重复的部分确定贪心思路)。

随后发现了在哪个位置钓鱼的收益与时间无关只和次数有关,接下来我们来思考一下能否将交换位置的时间剥离出来。

显然是可以的,随后我们可以枚举终点位置,即:每次只在1 ~ x的鱼塘内钓鱼。

接下来就变成了多个链表求最优和的问题。

可以发现每一个位置都是一个等差数列,并且考虑到有多个位置,每个位置地位相当,我们考虑使用多路归并算法。

有的人可能没有听说过这个算法,但其实这个算法很简单,合并两个有序数组用的就是多路归并算法。

随后根据等差数列的性质,最大的数字一定会出现在最表层,所以我们用堆来查找出外层的最大值依次增加即可。


代码

// 贪心 + 多路归并,枚举1 ~ n,每次多路归并查找
// 时间复杂度: n * t * logN, 时间肯定够。
#include<iostream>
#include<cstring>
#include<queue>
#define s second
#define f first
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int n, T, mx;
int a[N], b[N], t[N], st[N];
priority_queue<PII> pq;int main()
{scanf("%d", &n);for(int i = 0; i < n; i++) scanf("%d", a + i);for(int i = 0; i < n; i++) scanf("%d", b + i);for(int i = 1; i < n; i++) scanf("%d", t + i);scanf("%d", &T);for(int i = 0; i < n; i++) //枚举从0到i{int s = 0, l = 0;pq = priority_queue<PII>(); //重构。memset(st, 0, sizeof(st)); for(int j = 0; j <= i; j++){pq.push({a[j], j}); s += t[j]; //第一部分贪心的时间}while(s < T){PII x = pq.top(); pq.pop();l += max(0, x.f); st[x.s]++; pq.push({a[x.s] - st[x.s] * b[x.s], x.s});s++;}mx = max(mx, l);}    printf("%d", mx);return 0;
}

http://www.dtcms.com/wzjs/490476.html

相关文章:

  • 聊城住房建设局网站b站推广是什么意思
  • 网站制作软件被起诉搜索大全引擎地址
  • 日本做音乐网站成都网站制作
  • 公司网站更换域名seo成创网络
  • 网站做cpa赚钱吗免费建站网站一级
  • 广州 互联网公司 网站首页seo优化裤子关键词
  • 兼职 做网站今日新闻摘抄50字
  • 帮做3d模型的网站5g网络优化培训
  • 店铺设计效果图郑州seo优化外包热狗网
  • 做的网站能撤掉吗经典软文范例大全
  • 一点空间网站建设驻马店网站seo
  • 东莞长安西安优化seo
  • 石排东莞网站建设搜索引擎app
  • 免费用的在线客服深圳网站设计实力乐云seo
  • 哈尔滨精致网站建设域名注册人查询
  • 上海大型网站建设公司排名小果seo实战培训课程
  • 免费做网络推广的网站可靠吗网站设计与制作
  • 做外贸网站价格活动策划
  • 做seo网站推广价格四种营销策略
  • 合肥网站建设搜王道下拉浏览器正能量网站免费
  • 炫酷的网页特效单页网站怎么优化
  • 东营网红餐厅广东网站营销seo方案
  • wordpress图片使用图床武汉网站优化公司
  • 温州网站建设服务器seo查询seo优化
  • wordpress用的什么前端长沙有实力seo优化公司
  • 网站备案和域名备案seo搜索引擎优化知乎
  • 做性事的视频网站名字全网营销公司排名前十
  • 青岛网站优化联系方式迅雷bt磁力链 最好用的搜索引擎
  • 网站开发武汉公司免费网站模板
  • 网站都需要什么类别百度搜索关键词热度