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

国内创意网页设计seo外包公司排名

国内创意网页设计,seo外包公司排名,成都网站建设哪儿济南兴田德润怎么联系,后台做网站的题目录 前言 超快速排序 分析 代码 小朋友排队 分析 代码 鱼塘钓鱼 分析 代码 前言 本来计划今天写五道题的,结果计划赶不上变化,谁能告诉我我的时间都去哪了。。。 今天给大家带来三道题目,两道逆序对问题,分别用归并排…

目录

前言

超快速排序

分析

代码

小朋友排队

分析

代码

鱼塘钓鱼

分析

代码


前言

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

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


超快速排序


分析

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

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

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

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

如何证明呢?这个简单。

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

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

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

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/165918.html

相关文章:

  • 漂亮的门户网站网络优化排名培训
  • 唐山建设局网站婚恋网站排名
  • 网站文件上传wordpress修改seo数据是什么意思
  • 新翼设计网站建设公司百度关键词推广费用
  • 北京 网站设计公司热门国际新闻
  • 电脑网站建设方案广告联盟app
  • 网站设计收费推广什么app佣金高
  • 学做家常菜的网站有哪些技能培训机构
  • 制作简单的站点推广方案株洲最新今日头条
  • 代备案网站郑州网站推广方案
  • 网站域名怎么缴费营销网站建设哪家快
  • 自己的网站如何做快照劫持seo品牌优化百度资源网站推广关键词排名
  • 深圳网站制作公司信息今日国际新闻大事件
  • 做网站框架浏览时怎么变长网站可以自己做吗
  • 无需登录免费观看的直播seo交互论坛
  • 资源库网站建设网络运营培训课程
  • 网站开发知识版权seo运营是什么
  • 耒阳市古雍网站建设店反向链接查询
  • 网站没有关键词如何建网站不花钱
  • 东莞网站推广哪家好威海seo优化公司
  • 怎样做网站维护广州网站优化价格
  • 网站是用php还是asp 怎么区别软文素材网站
  • wordpress文字数据库windows优化大师要会员
  • 创建网站代码西安网站优化培训
  • 做废钢推广网站使用网站模板快速建站
  • 做seo必须有自己网站吗交换链接营销案例
  • 宿迁建设局网站好搜自然seo
  • 做网站最便宜要多少钱如何写软文
  • 前端开发主要做什么seo怎么做?
  • 漳州开发区人才网seo网站排名优化软件是什么