• CSP-J2021-插入排序


    [CSP-J 2021] 插入排序 - 洛谷


    解题思路:

    1.分析题意,排序的伪代码是从小到大,并且如果相邻的两个元素数值一样的话,不发生交换,属于稳定排序,操作1是将第X下标位置的元素值修改为v,是保留这种操作的,操作2是将数组进行一次排序,然后访问第X个元素在排序后的位置,这种操作是不保留的,不会影响后续操作

    2.如果利用模拟思路来做,那么可以创建一个结构体变量,存储每一个元素的编号id和值num,然后设置一个cmp函数,如果发生了操作2,那么对数组进行一次sort排序,然后访问编号为x的元素,输出此时的下标位置,如果发生了操作1,遍历数组将id为x的位置的元素值修改为v


    1. #include
    2. using namespace std;
    3. struct node{
    4. int id;//存储编号
    5. int num;//存储值
    6. }a[8010];
    7. bool cmp(node aa,node bb)//快速排序
    8. {
    9. if(aa.num!=bb.num)//如果两个值不等的话
    10. return aa.num//值小的在前
    11. else//如果值相等的话
    12. return aa.id//编号小的在前
    13. }
    14. int main()
    15. {
    16. int n,q;
    17. cin>>n>>q;
    18. for(int i=1;i<=n;i++)
    19. {
    20. cin>>a[i].num;
    21. a[i].id=i;
    22. }//将编号和元素值存入结构体数组a中
    23. int x,y,z;
    24. while(q--)//进行q次操作
    25. {
    26. cin>>x;//输入第一个数
    27. if(x==1)//如果是操作1的话
    28. {
    29. cin>>y>>z;//接着输入两个数
    30. for(int i=1;i<=n;i++)//在数组a中寻找编号为y的元素
    31. {
    32. if(a[i].id==y)//如果找到了
    33. {
    34. a[i].num=z;//将此位置的值修改为z
    35. break;//结束循环
    36. }
    37. }
    38. }
    39. else//如果是操作2的话
    40. {
    41. cin>>y;//输入一个数
    42. sort(a+1,a+n+1,cmp);//进行一次排序
    43. for(int i=1;i<=n;i++)//在数组中找一下编号为y的值
    44. {
    45. if(a[i].id==y)//如果找到了
    46. {
    47. cout<//输出现在所在的位置
    48. break;//结束程序
    49. }
    50. }
    51. }
    52. }
    53. return 0;
    54. }

    优化思路:

    1.分析数据,发现q最大为2*10^5,而操作1最多有5000次,那么sort的时间复杂度为O(nlogn),如果发生20万次快排,显然会超时,所以排序的地方是需要优化的思路

    2.试想,如果模拟插入排序的思路,首先对数组a进行稳定排序,如果发生了操作1的话,修改单点的值,因为本来是排好的顺序,如果修改了此时的点,那么顺序便会被打乱,但是可以将此时修改的值和原来的值比一下,如果改大了,那么他应该往后插,如果改小了,应该往前插,如果值相等,那么比编号,编号小的在前,这样,总共有8000个元素,利用插排可以将时间复杂度降到O(n),大大节省了时间

    3.再来考虑操作2,要求访问原数组编号为y的在排序后的位置,那么可以建立一个数组b,来存每个数组a对应的位置,比如编号为4的元素最小,排在第一位,那么b[1]=4,只要访问一下数组b元素值为y的下标便是数组a在排序后的位置(注意,每发生一次操作1,便要重新给数组b赋值


    1. #include
    2. using namespace std;
    3. struct node{
    4. int id;//存储编号
    5. int num;//存储值
    6. }a[8010];
    7. int b[8010];
    8. bool cmp(node aa,node bb)//快速排序
    9. {
    10. if(aa.num!=bb.num)//如果两个值不等的话
    11. return aa.num//值小的在前
    12. else//如果值相等的话
    13. return aa.id//编号小的在前
    14. }
    15. int main()
    16. {
    17. int n,q;
    18. cin>>n>>q;
    19. for(int i=1;i<=n;i++)
    20. {
    21. cin>>a[i].num;
    22. a[i].id=i;
    23. }//将编号和元素值存入结构体数组a中
    24. sort(a+1,a+n+1,cmp);//对数组a进行稳定排序
    25. for(int i=1;i<=n;i++)
    26. {
    27. b[i]=a[i].id;//将此时数组a编号的位置充当数组b的元素值
    28. }
    29. int x,y,z;
    30. while(q--)//进行q次操作
    31. {
    32. cin>>x;//输入第一个数
    33. if(x==1)//如果是操作1的话
    34. {
    35. cin>>y>>z;//接着输入两个数
    36. int ans;//ans保存原来编号为y的数组a的元素值
    37. int flag;//flag保存原来编号y的数组a排序后的下标位置
    38. for(int i=1;i<=n;i++)
    39. {
    40. if(a[i].id==y)//找到编号所在的位置
    41. {
    42. ans=a[i].num;//记录此时的元素值
    43. flag=i;//记录此时的下标
    44. break;
    45. }
    46. }
    47. if(z>ans)//如果这个点的值修改的大了
    48. {
    49. a[flag].num=z;//将此下标的元素值修改为z
    50. for(int i=flag;i<=n-1;i++)
    51. {
    52. if(a[i].num>a[i+1].num||(a[i].num==a[i+1].num&&a[i].id>a[i+1].id))
    53. {
    54. swap(a[i],a[i+1]);//交换两个元素值
    55. }//如果当前位置的元素值比后面的大或者值一样大,但是编号比后面的大的话
    56. }
    57. }
    58. else if(z//如果修改的值比原来的小了
    59. {
    60. a[flag].num=z;//将此下标的元素值修改为z
    61. for(int i=flag;i>=2;i--)
    62. {
    63. if(a[i].num-1].num||(a[i].num==a[i-1].num&&a[i].id-1].id))
    64. {
    65. swap(a[i],a[i-1]);//交换两个元素值
    66. }//如果当前位置的元素值比前面的小或者值一样大,但是编号比前面的小的话
    67. }
    68. }
    69. for(int i=1;i<=n;i++)//重新更新数组b的元素值,因为数组a重新排序了
    70. {
    71. b[i]=a[i].id;
    72. }
    73. }
    74. else//如果是操作2的话
    75. {
    76. cin>>y;//输入一个数
    77. for(int i=1;i<=n;i++)//在数组b中寻找编号为y的值
    78. {
    79. if(b[i]==y)//如果找到了
    80. {
    81. cout<//输出此时数组b的下标
    82. break;
    83. }
    84. }
    85. }
    86. }
    87. return 0;
    88. }

    继续优化:

    1.在上述代码中,发现每次执行操作2,都会重新访问一次数组b,那如果试着将数组b的下标设置为数组a元素的下标,而数组b的元素值设置成排序后的编号的话,那么执行操作2直接cout<

    2.那么在进行操作1的修改的时候,直接就能确定要修改的元素位置,即a[b[y].num,此处也省去了O(n)的时间


    1. #include
    2. using namespace std;
    3. struct node{
    4. int id;//存储编号
    5. int num;//存储值
    6. }a[8010];
    7. int b[8010];
    8. bool cmp(node aa,node bb)//快速排序
    9. {
    10. if(aa.num!=bb.num)//如果两个值不等的话
    11. return aa.num//值小的在前
    12. else//如果值相等的话
    13. return aa.id//编号小的在前
    14. }
    15. int main()
    16. {
    17. int n,q;
    18. cin>>n>>q;
    19. for(int i=1;i<=n;i++)
    20. {
    21. cin>>a[i].num;
    22. a[i].id=i;
    23. }//将编号和元素值存入结构体数组a中
    24. sort(a+1,a+n+1,cmp);//对数组a进行稳定排序
    25. for(int i=1;i<=n;i++)
    26. {
    27. b[a[i].id]=i;//将排序好的数组a的编号作为b数组的下标,数组b的元素值是数组a排好序的编号
    28. }
    29. int x,y,z;
    30. while(q--)//进行q次操作
    31. {
    32. cin>>x;//输入第一个数
    33. if(x==1)//如果是操作1的话
    34. {
    35. cin>>y>>z;//接着输入两个数
    36. int ans=a[b[y]].num;//ans保存原来编号为y的数组a的元素值
    37. int flag=b[y];//flag保存原来编号y的数组a排序后的下标位置
    38. if(z>ans)//如果这个点的值修改的大了
    39. {
    40. a[flag].num=z;//将此下标的元素值修改为z
    41. for(int i=flag;i<=n-1;i++)
    42. {
    43. if(a[i].num>a[i+1].num||(a[i].num==a[i+1].num&&a[i].id>a[i+1].id))
    44. {
    45. swap(a[i],a[i+1]);//交换两个元素值
    46. }//如果当前位置的元素值比后面的大或者值一样大,但是编号比后面的大的话
    47. }
    48. }
    49. else if(z//如果修改的值比原来的小了
    50. {
    51. a[flag].num=z;//将此下标的元素值修改为z
    52. for(int i=flag;i>=2;i--)
    53. {
    54. if(a[i].num-1].num||(a[i].num==a[i-1].num&&a[i].id-1].id))
    55. {
    56. swap(a[i],a[i-1]);//交换两个元素值
    57. }//如果当前位置的元素值比前面的小或者值一样大,但是编号比前面的小的话
    58. }
    59. }
    60. for(int i=1;i<=n;i++)//重新更新数组b的元素值,因为数组a重新排序了
    61. {
    62. b[a[i].id]=i;
    63. }
    64. }
    65. else//如果是操作2的话
    66. {
    67. cin>>y;//输入一个数
    68. cout<
    69. }
    70. }
    71. return 0;
    72. }
  • 相关阅读:
    unity shader 常见的混合类型
    经典算法-----迷宫问题(栈的应用)
    【ROS2原理5】从ROS1到ROS2的变迁
    Python读取hbase数据库
    大一学生期末大作业 html+css+javascript网页设计实例【电影购票项目】html网页制作成品代码
    import cv2 No module named ‘cv2‘
    如何清除运行 Docker 容器的日志
    Chainlink Keepers 能够帮助 Web3 开发者更快开发的 7 个特性
    UNPV2 学习:System V IPC 章节学习问题记录
    【计算机网络笔记】计算机网络的结构
  • 原文地址:https://blog.csdn.net/weixin_60869516/article/details/126415356