• 2023CCPC哈尔滨站


    2023CCPC哈尔滨站icon-default.png?t=N7T8https://contest.ucup.ac/contest/1412

    B. Memory 

    1. int main() {
    2. int n;
    3. std::cin >> n;
    4. std::vector<int> a(n);
    5. for (int i = 0; i < n; i++) {
    6. std::cin >> a[i];
    7. }
    8. std::string res;
    9. int x = 0, Dec = 0;
    10. // 整数位 x 和 小数位符号 Dec
    11. for (int i = 0; i < n; i++) {
    12. x += a[i];
    13. if (x != 0)
    14. res.push_back(x > 0 ? '+' : '-');
    15. else {
    16. if (Dec != 0)
    17. res.push_back(Dec > 0 ? '+' : '-');
    18. else
    19. res.push_back('0');
    20. }
    21. if (std::abs(x) & 1)
    22. Dec = (x > 0 ? 1 : -1);
    23. x /= 2;
    24. }
    25. std::cout << res;
    26. }

    G. The Only Way to the Destination

    思路:

    题意中给出了几个很重要的信息:

    1、墙只有纵向
    2、爱丽丝确保在放置 k 面墙后,所有空网格都保持连接,迷宫中至少有一个空网格。并且保证不同的墙没有共同的网格
    3、保证每对空格之间至少有一条简单路径相连

    本来的想法是bfs,但是数据量过大,想想看如果有多条简单路径时会怎么样。

    首先对两列,如果左边连续的空网格和右边连续的空网格结合在一起,那么肯定不行,比如第三个样例,第二列两个连续的空网格和第三列两个连续的空网格形成了一个2*2的空格,这时不管其他地方怎么样,一定不可能满足条件了。

    因此如果 n > 1 时,每两列必须要有一堵墙,否则两个空列接在一起一定不可能满足条件,这样的话 m 最多只有2k+1,否则一定不可能满足条件。而 n = 1时由于一定会有一条简单路径,而且也不可能出现其他简单路径,这时一定满足条件,特判直接返回即可。

    其次,如果有多条简单路径,还不是连续网格相接,那么一定是环造成的。一个最简单的环就是一个矩形,这时它两边会有两个竖线(也就是连续空网格)将上下两条线相连,从左到右画的话,在连上后面的竖线时,就会导致成环,也就是把两个联通的部分又连接起来了,而成环的话,就必须有一条竖线把联通部分再相连。因此我们只用看后面的这段连续的空网格是否将多个联通的部分连接起来即可。

    我们可以从左到右枚举列,对每一列,从上到下枚举连续空网格区间,看他是否将前面多个联通的部分再次相连。也就是枚举前面一列对应的区间内的空网格区间,判断两两是否联通,如果有联通,就说明有环,答案就是NO,否则将它们联通起来。

    如何判断联通:

    • 如果前面一列没区间,说明这一块是凭空产生的,分配一个颜色
    • 有区间的话如果不连通的颜色都唯一,这时这几种颜色联通,并查集维护一致性
    • 如果某个联通的颜色不唯一,说明无解
    1. # include <iostream>
    2. # include <vector>
    3. # include <algorithm>
    4. using namespace std;
    5. struct wall
    6. {
    7. int x1, x2, y;
    8. bool operate<(wall x) // 重载小于号,用于排序
    9. {
    10. if (y != x.y)
    11. return y<x.y;
    12. return x1 < x.x1;
    13. }
    14. }w[10000];
    15. int n, m, k;
    16. struct node
    17. {
    18. int l, r, color; // 记录连续空区间的左右端点,及其颜色
    19. };
    20. vector<node> lst, cur; // lst表示前一列的空区间, cur 表示当前枚举这一列的空区间
    21. int c, f[10000];
    22. // 使用并查集,保持统一性
    23. int find(int x)
    24. {
    25. while (x != f[x])
    26. x = f[x];
    27. return x;
    28. }
    29. void merge(int x, int y)
    30. {
    31. f[find(y)] = find(x);
    32. }
    33. int findl(int l)
    34. {
    35. for (int i=0; i<lst.size(); ++i)
    36. if (lst[i].r >= l)
    37. return i;
    38. return -1;
    39. }
    40. int findr(int r)
    41. {
    42. for (int i=lst.size()-1; i>=0; --i)
    43. {
    44. if (lst[i].l <= r)
    45. return i;
    46. }
    47. return -1;
    48. }
    49. bool solve()
    50. {
    51. if (n == 1)
    52. return true;
    53. for (int i=1; i<10000; ++i)
    54. f[i] = i;
    55. for (int col = 1, i = 0; lstr; col<=m; ++col)
    56. {
    57. lstr = 0; // 记录上一个墙的右端点, 因此可以计算出下一段空区间为[lstr+1, w[].x1-1]
    58. cur.clear();
    59. while(i+1<=k && w[i+1].y == col)
    60. {
    61. i++;
    62. if (lstr+1 <= w[i].x1-1)
    63. {
    64. cur.push_back((node){lstr+1, w[i].x1-1, -1}); // 中间有空隙
    65. }
    66. lstr = w[i].x2;
    67. }
    68. if (lstr+1 <= n)
    69. cur.push_back((node){lstr+1, n, -1});
    70. int l, r, lidx, ridx, lstf; // 枚举空区间的左右端点,以及前一个左右区间
    71. for (auto &tmp: cur)
    72. {
    73. l = tmp.l;
    74. r = tmp.r;
    75. lidx = findl(l);
    76. ridx = findr(r);
    77. lstf = -1; // 所属颜色
    78. for (int i=lidx, tl, tr; i<=ridx; ++i)
    79. {
    80. tl = max(l, lst[i].l);
    81. tr = min(r, lst[i].r);
    82. if (tr - tl >= 1)
    83. return false;
    84. if (lstf != -1)
    85. {
    86. if (find(lst[i].color != lstf))
    87. merge(lstf, lst[i].color);
    88. else
    89. return false; // 两个颜色已经连通
    90. }
    91. else
    92. lstf = find(lst[i].color);
    93. }
    94. if (lstf != -1)
    95. tmp.color = lstf;
    96. else
    97. {
    98. tmp.color = c;
    99. c++;
    100. }
    101. }
    102. lst = cur; //对lst重新初始化 使其表示前一列
    103. }
    104. return true;
    105. }
    106. int main()
    107. {
    108. cin >> n >> m >> k;
    109. for (int i=1; i<=k; ++i)
    110. {
    111. cin >> w[i].x1 >> w[i].x2 >> w[i].y;
    112. }
    113. sort(w+1, w+k+1);
    114. if (solve())
    115. cout << "yes";
    116. else
    117. cout << "no";
    118. }

    L.Palm Island

    1. #include <iostream>
    2. #include <cstdio>
    3. #include <algorithm>
    4. using namespace std;
    5. const int maxn=1005;
    6. int T,n;
    7. int a[maxn],t[maxn];
    8. pair<int,int> b[maxn];
    9. int main(){
    10. cin>>T;
    11. while(T--){
    12. cin>>n;
    13. for(int i=1;i<=n;i++)
    14. cin>>t[i];
    15. for(int i=1;i<=n;i++){
    16. b[i].second=i;
    17. cin>>b[i].first;
    18. }
    19. sort(b+1,b+n+1);
    20. for(int i=1;i<=n;i++)
    21. a[i]=b[t[i]].second;
    22. for(int round=1;round<n;round++){
    23. for(int i=1;i<n;i++)
    24. if(a[i]>a[i+1]){
    25. swap(a[i],a[i+1]);
    26. printf("2");
    27. }
    28. else printf("1");
    29. printf("1");
    30. }
    31. puts("");
    32. }
    33. return 0;
    34. }

  • 相关阅读:
    LLVM系列第二十八章:写一个JIT Hello World
    k8s containerd集群配置安装完整踩坑教程
    麒麟系统修改网卡名步骤和网卡占用故障处理
    Java:2022年全球使用的15种最流行的Java应用
    现代 CSS 解决方案:文字颜色自动适配背景色!
    顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-webrtc(浏览器直接拨打电话)
    剑指Offer面试题解总结31~40
    C++智能指针
    【iOS ARKit】网络传输 ARWorldMap
    css实现的悬停菜单鼠标跟随图片显示交互特效html页面前端源码
  • 原文地址:https://blog.csdn.net/2301_80610560/article/details/139452681