2 条题解
-
20
假设比较两个元素的时间为 \mathcal O(1)O(1),则插入排序可以以 \mathcal O(n^2)O(n2) 的时间复杂度完成长度为 nn 的数组的排序。不妨假设这 nn 个数字分别存储在 a_1, a_2, \ldots, a_na1,a2,…,an 之中,则如下伪代码给出了插入排序算法的一种最简单的实现方式:
这下面是 C/C++ 的示范代码:
for (int i = 1; i <= n; i++) for (int j = i; j >= 2; j--) if (a[j] < a[j-1]) { int t = a[j-1]; a[j-1] = a[j]; a[j] = t; }
这下面是 Pascal 的示范代码:
for i:=1 to n do for j:=i downto 2 do if a[j]<a[j-1] then begin t:=a[i]; a[i]:=a[j]; a[j]:=t; end;
讲解
定义
首先我们要定义一个结构体数组,有两个元素,分别是需要存储的量和它的序号,用来存储在排序前他们分别占的位置,必须定义!数组的长度应是8000,因为n的值最大是8000,我们多开五个空间。
struct node { int num,id;//数组里的值原和序号 }a[8005];
还需要定义一个b数组,用来存放他们排序后的序号,b应是一个一维数组
int b[8005];
输入
输入的时候应该边输入并计算它的序号,序号就是循环的i
for(i=1;i<=n;i++)//输入元素 { cin>>a[i].num; a[i].id=i;//计算标号 }
初始化
操作二需要把a数组进行排序,可操作二的次数不确定,会超时,所以我们应该把排序的任务放在操作一之后以及输入之后。
所干的事情应该是把a数组的元素进行排序,可以用sort函数,(详细使用方法见文章讲解C++中的sort(快速排序函数)),并且把a数组的下标存入b数组里。
sort(a+1,a+1+n,cmp);//排序 for(i=1;i<=n;i++) b[a[i].id]=i;//将a数组的序号顺序存入b数组
进行操作 首先进行q次循环,可以用while。
每次循环,先输入操作类型,然后判断操作类型是一还是二。
操作一 输入x和v先进行修改的任务,只需将原来a数组的第x个元素改v,再重新进行排序,再把存好的a数组的下标存起来,但排序a数组时不能再使用sort函数了,因为这样会超时,那么应该怎么优化呢,不难看出,a数组的元素中,只有一个修改的数是乱的,其余的数排序都是升序排好的,所以我们可以使用两个for循环,一个正着遍历一遍,另一个反着遍历一遍,如果这个数字比前面一个数小,则反着遍历的for可以把它存到适当的位置;反之,如果这个数字比后一个数还要大,则正序遍历的for可以把它存到适当的位置。而这两个for是顺序关系,时间复杂度只有2n,远比sort要快的多
cin>>x>>v; a[b[x]].num=v;//改变数组的元素 for(i=1;i<=n-1;i++) if(cmp(a[i],a[i+1])==0) swap(a[i],a[i+1]);//向后排序 for(i=n;i>=2;i--) if(cmp(a[i-1],a[i])==0) swap(a[i-1],a[i]);//向前排序 for(i=1;i<=n;i++) b[a[i].id]=i;//对下标重新排序
操作二
如果是操作二的话,只需要输出b数组里的下标就行了
cin>>x;//序号为x的数排序后在哪里 cout<<b[x]<<endl;//输出
最终代码+注释
#include<bits/stdc++.h> using namespace std; struct node { int num,id;//数组里的值原和序号 }a[8005]; bool cmp(node a,node b)//排序规则 { if(a.num==b.num)//值相同 return a.id<b.id;//根据序号升序排 return a.num<b.num;//值不相同按序号升序排 } int main() { int b[8005],n,q,i; cin>>n>>q;//输入几个数和几次操作 for(i=1;i<=n;i++)//输入元素 { cin>>a[i].num; a[i].id=i;//计算标号 } sort(a+1,a+1+n,cmp);//排序 for(i=1;i<=n;i++) b[a[i].id]=i;//将a数组的序号顺序存入b数组 while(q--)//进行q次操作 { int s,x,v; cin>>s;//第几种操作 if(s==1)//操作一 { cin>>x>>v; a[b[x]].num=v;//改变数组的元素 for(i=1;i<=n-1;i++) if(cmp(a[i],a[i+1])==0) swap(a[i],a[i+1]);//向后排序 for(i=n;i>=2;i--) if(cmp(a[i-1],a[i])==0) swap(a[i-1],a[i]);//向前排序 for(i=1;i<=n;i++) b[a[i].id]=i;//对下标重新排序 } else//操作二 { cin>>x;//序号为x的数排序后在哪里 cout<<b[x]<<endl;//输出 } } return 0; }
-
0
#include<bits/stdc++.h> using namespace std; struct node { int num,id;//数组里的值原和序号 }a[8005]; bool cmp(node a,node b)//排序规则 { if(a.num==b.num)//值相同 return a.id<b.id;//根据序号升序排 return a.num<b.num;//值不相同按序号升序排 } int main() { int b[8005],n,q,i; cin>>n>>q;//输入几个数和几次操作 for(i=1;i<=n;i++)//输入元素 { cin>>a[i].num; a[i].id=i;//计算标号 } sort(a+1,a+1+n,cmp);//排序 for(i=1;i<=n;i++) b[a[i].id]=i;//将a数组的序号顺序存入b数组 while(q--)//进行q次操作 { int s,x,v; cin>>s;//第几种操作 if(s==1)//操作一 { cin>>x>>v; a[b[x]].num=v;//改变数组的元素 for(i=1;i<=n-1;i++) if(cmp(a[i],a[i+1])==0) swap(a[i],a[i+1]);//向后排序 for(i=n;i>=2;i--) if(cmp(a[i-1],a[i])==0) swap(a[i-1],a[i]);//向前排序 for(i=1;i<=n;i++) b[a[i].id]=i;//对下标重新排序 } else//操作二 { cin>>x;//序号为x的数排序后在哪里 cout<<b[x]<<endl;//输出 } } return 0; }
- 1
信息
- ID
- 1355
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 456
- 已通过
- 147
- 上传者