鱼C论坛

 找回密码
 立即注册
查看: 2388|回复: 11

[已解决]一道C++实验题(线段树使用)

[复制链接]
发表于 2021-10-24 18:03:22 | 显示全部楼层 |阅读模式
30鱼币
题目简单来说就是 第一行输入  请求数量 (n)    区间大小(size)

接下来有n行输入  每行有个起始时间 和 结束时间
先到先得, 如果这段时间被先前的请求占用了 就拒绝 否则接受
我感觉这题就是 判断 这一条线段  是否有被占用
我自己拿数组写了 发现时间复杂度太大了 可能会超时

不知道有没有大佬 可以帮忙用线段树写一下
最佳答案
2021-10-24 18:03:23
1248762042 发表于 2021-10-24 23:33
他就是不给测试数据的

我就讨厌这样的刷题网站,用于判断的那个程序完全知道 输入数据、正确答案、你程序给出的答案
但是这个程序是这样说的,你写的这个程序不对,至于有什么问题,我不告诉你,你自己去看代码,改代码
一个好的刷题网站应该是这样的
你的这个程序不正确,在输入 1234 的时候,正确的输出应该是 1,但是你提供的程序输出的是 0
你看这样不好吗?有了输入数据、正确答案、错误答案,可以非常快速的定位代码中存在的问题
对于前面的那个刷题网站,他不告诉我这 3 个数据,我只能一行代码一行代码的找问题,想了又想,是哪里漏掉了某种情况?
我非常非常讨厌这样的刷题网站,因为代码出现问题根本没法修改代码,因为不知道这 3 个数据,输入数据、正确答案、错误答案


好了,下面说正事
再试一下这个代码,这次用了 线段树(大概,^_^)
segment_tree.hpp
  1. #ifndef _SEGMENT_TREE_HPP_
  2. #define _SEGMENT_TREE_HPP_

  3. #include <cstddef>

  4. template <typename T>
  5. class segment_tree_t {
  6. public:
  7.     segment_tree_t(size_t begin, size_t end, T value = T()): root(nullptr) {
  8.         if(begin > end) return;
  9.         root = create(begin, end, value);
  10.     }
  11.     ~segment_tree_t() {
  12.         free(root);
  13.     }
  14.     bool get(size_t begin, size_t end, long long &sum) {
  15.         if(!root) return false;
  16.         if(begin > end) return false;
  17.         sum = get_sub(root, begin, end);
  18.         return true;
  19.     }
  20.     bool set(size_t begin, size_t end, T value) {
  21.         if(!root) return false;
  22.         if(begin > end) return false;
  23.         set_sub(root, begin, end, value);
  24.         return true;
  25.     }
  26. private:
  27.     struct node_t {
  28.         size_t begin, end;
  29.         T value;
  30.         node_t *lchrild, *rchrild;
  31.     };
  32.     node_t *root;
  33.     static node_t *create(size_t begin, size_t end, T value) {
  34.         node_t *root = new node_t();
  35.         root->begin = begin;
  36.         root->end = end;
  37.         if(begin == end) {
  38.             root->lchrild = root->rchrild = nullptr;
  39.             root->value = value;
  40.             return root;
  41.         }
  42.         size_t middle = (begin + end) / 2;
  43.         root->lchrild = create(begin, middle, value);
  44.         root->rchrild = create(middle + 1, end, value);
  45.         root->value = root->lchrild->value + root->rchrild->value;
  46.         return root;
  47.     }
  48.     static void free(node_t *root) {
  49.         if(!root) return;
  50.         free(root->lchrild);
  51.         free(root->rchrild);
  52.         delete root;
  53.     }
  54.     static long long get_sub(node_t *root, size_t begin, size_t end) {
  55.         if(root->begin > end || root->end < begin) return 0;
  56.         if(root->begin >= begin && root->end <= end) return root->value;
  57.         return get_sub(root->lchrild, begin, end) + get_sub(root->rchrild, begin, end);
  58.     }
  59.     static void set_sub(node_t *root, size_t begin, size_t end, T value) {
  60.         if(root->begin > end || root->end < begin) return;
  61.         if(root->begin == root->end) {root->value = value; return;}
  62.         set_sub(root->lchrild, begin, end, value);
  63.         set_sub(root->rchrild, begin, end, value);
  64.         root->value = root->lchrild->value + root->rchrild->value;
  65.     }
  66.     segment_tree_t(const segment_tree_t &rhs) = delete;
  67.     segment_tree_t &operator=(const segment_tree_t &rhs) = delete;
  68. };

  69. #endif
复制代码


main.cpp
  1. #include <iostream>
  2. #include "segment_tree.hpp"

  3. int main() {
  4.     size_t n, m; std::cin >> n >> m;
  5.     segment_tree_t<size_t> st(1, m);
  6.     for(size_t i = 0; i < n; ++i) {
  7.         size_t l, r; std::cin >> l >> r;
  8.         long long sum;
  9.         st.get(l, r, sum);
  10.         if(sum == 0) {
  11.             st.set(l, r, 1);
  12.             std::cout << "ACCEPTED" << std::endl;
  13.         } else std::cout << "REJECTED" << std::endl;
  14.     }
  15.     return 0;
  16. }
复制代码
9(MT0E{B~]HSM31O7Y04(]6.png

最佳答案

查看完整内容

我就讨厌这样的刷题网站,用于判断的那个程序完全知道 输入数据、正确答案、你程序给出的答案 但是这个程序是这样说的,你写的这个程序不对,至于有什么问题,我不告诉你,你自己去看代码,改代码 一个好的刷题网站应该是这样的 你的这个程序不正确,在输入 1234 的时候,正确的输出应该是 1,但是你提供的程序输出的是 0 你看这样不好吗?有了输入数据、正确答案、错误答案,可以非常快速的定位代码中存在的问题 对于前面 ...
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-24 18:03:23 | 显示全部楼层    本楼为最佳答案   
1248762042 发表于 2021-10-24 23:33
他就是不给测试数据的

我就讨厌这样的刷题网站,用于判断的那个程序完全知道 输入数据、正确答案、你程序给出的答案
但是这个程序是这样说的,你写的这个程序不对,至于有什么问题,我不告诉你,你自己去看代码,改代码
一个好的刷题网站应该是这样的
你的这个程序不正确,在输入 1234 的时候,正确的输出应该是 1,但是你提供的程序输出的是 0
你看这样不好吗?有了输入数据、正确答案、错误答案,可以非常快速的定位代码中存在的问题
对于前面的那个刷题网站,他不告诉我这 3 个数据,我只能一行代码一行代码的找问题,想了又想,是哪里漏掉了某种情况?
我非常非常讨厌这样的刷题网站,因为代码出现问题根本没法修改代码,因为不知道这 3 个数据,输入数据、正确答案、错误答案


好了,下面说正事
再试一下这个代码,这次用了 线段树(大概,^_^)
segment_tree.hpp
  1. #ifndef _SEGMENT_TREE_HPP_
  2. #define _SEGMENT_TREE_HPP_

  3. #include <cstddef>

  4. template <typename T>
  5. class segment_tree_t {
  6. public:
  7.     segment_tree_t(size_t begin, size_t end, T value = T()): root(nullptr) {
  8.         if(begin > end) return;
  9.         root = create(begin, end, value);
  10.     }
  11.     ~segment_tree_t() {
  12.         free(root);
  13.     }
  14.     bool get(size_t begin, size_t end, long long &sum) {
  15.         if(!root) return false;
  16.         if(begin > end) return false;
  17.         sum = get_sub(root, begin, end);
  18.         return true;
  19.     }
  20.     bool set(size_t begin, size_t end, T value) {
  21.         if(!root) return false;
  22.         if(begin > end) return false;
  23.         set_sub(root, begin, end, value);
  24.         return true;
  25.     }
  26. private:
  27.     struct node_t {
  28.         size_t begin, end;
  29.         T value;
  30.         node_t *lchrild, *rchrild;
  31.     };
  32.     node_t *root;
  33.     static node_t *create(size_t begin, size_t end, T value) {
  34.         node_t *root = new node_t();
  35.         root->begin = begin;
  36.         root->end = end;
  37.         if(begin == end) {
  38.             root->lchrild = root->rchrild = nullptr;
  39.             root->value = value;
  40.             return root;
  41.         }
  42.         size_t middle = (begin + end) / 2;
  43.         root->lchrild = create(begin, middle, value);
  44.         root->rchrild = create(middle + 1, end, value);
  45.         root->value = root->lchrild->value + root->rchrild->value;
  46.         return root;
  47.     }
  48.     static void free(node_t *root) {
  49.         if(!root) return;
  50.         free(root->lchrild);
  51.         free(root->rchrild);
  52.         delete root;
  53.     }
  54.     static long long get_sub(node_t *root, size_t begin, size_t end) {
  55.         if(root->begin > end || root->end < begin) return 0;
  56.         if(root->begin >= begin && root->end <= end) return root->value;
  57.         return get_sub(root->lchrild, begin, end) + get_sub(root->rchrild, begin, end);
  58.     }
  59.     static void set_sub(node_t *root, size_t begin, size_t end, T value) {
  60.         if(root->begin > end || root->end < begin) return;
  61.         if(root->begin == root->end) {root->value = value; return;}
  62.         set_sub(root->lchrild, begin, end, value);
  63.         set_sub(root->rchrild, begin, end, value);
  64.         root->value = root->lchrild->value + root->rchrild->value;
  65.     }
  66.     segment_tree_t(const segment_tree_t &rhs) = delete;
  67.     segment_tree_t &operator=(const segment_tree_t &rhs) = delete;
  68. };

  69. #endif
复制代码


main.cpp
  1. #include <iostream>
  2. #include "segment_tree.hpp"

  3. int main() {
  4.     size_t n, m; std::cin >> n >> m;
  5.     segment_tree_t<size_t> st(1, m);
  6.     for(size_t i = 0; i < n; ++i) {
  7.         size_t l, r; std::cin >> l >> r;
  8.         long long sum;
  9.         st.get(l, r, sum);
  10.         if(sum == 0) {
  11.             st.set(l, r, 1);
  12.             std::cout << "ACCEPTED" << std::endl;
  13.         } else std::cout << "REJECTED" << std::endl;
  14.     }
  15.     return 0;
  16. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-24 19:30:07 | 显示全部楼层
不知道这样行不行
  1. #include <iostream>
  2. #include <vector>

  3. bool submit(std::vector<bool> &v, size_t begin, size_t end) {
  4.     if(begin >= end) return false;
  5.     if(v.size() < end) return false;
  6.     for(size_t i = begin; i < end; ++i) {
  7.         if(!v[i]) return false;
  8.     }
  9.     for(size_t i = begin; i < end; ++i) {
  10.         v[i] = false;
  11.     }
  12.     return true;
  13. }

  14. int main() {
  15.     size_t n, m; std::cin >> n >> m;
  16.     std::vector<bool> v(m, true);
  17.     for(size_t i = 0; i < n; ++i) {
  18.         size_t l, r; std::cin >> l >> r;
  19.         if(submit(v, l - 1, r)) std::cout << "ACCEPTED" << std::endl;
  20.         else std::cout << "REJECTED" << std::endl;
  21.     }
  22.     return 0;
  23. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-10-24 20:16:24 | 显示全部楼层
人造人 发表于 2021-10-24 19:30
不知道这样行不行

答案是对的, 但这个就是像我先前写的暴力查找,测试数据里面有百万级别的,很可能超时, 我们老师说让我们拿线段树试试
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-24 20:23:10 | 显示全部楼层
1248762042 发表于 2021-10-24 20:16
答案是对的, 但这个就是像我先前写的暴力查找,测试数据里面有百万级别的,很可能超时, 我们老师说让我们拿 ...

那我研究研究 线段树
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-24 22:09:28 | 显示全部楼层
扫了一眼,推荐使用map映射,哈希算法的值不会随着数据增加而变长,
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-24 23:04:23 | 显示全部楼层
我看了半天线段树,没有看出线段树比我这个程序有什么优势,你发一下题目的链接,我去看一下是哪一个输入数据导致了我的程序超时的
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-24 23:10:19 | 显示全部楼层
嗯,我好像是有点理解了,但是你还是发一下链接吧
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-10-24 23:33:01 | 显示全部楼层
人造人 发表于 2021-10-24 23:10
嗯,我好像是有点理解了,但是你还是发一下链接吧

他就是不给测试数据的
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-25 10:46:47 | 显示全部楼层
1248762042 发表于 2021-10-24 23:33
他就是不给测试数据的

换一个刷题网站吧,这样的刷题网站,代码出现问题没法改,真的没法改,你只能是盯着代码一行一行的看,看哪里漏掉了某种情况,这是非常痛苦的一件事
但是有了那 3 个数据,可以非常快速的定位代码中的问题
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-25 10:49:14 | 显示全部楼层
main.cpp 改一下吧,改成这样
  1. #include <iostream>
  2. #include "segment_tree.hpp"

  3. int main() {
  4.     size_t n, m; std::cin >> n >> m;
  5.     segment_tree_t<size_t> st(1, m);
  6.     for(size_t i = 0; i < n; ++i) {
  7.         size_t l, r; std::cin >> l >> r;
  8.         long long sum;
  9.         if(st.get(l, r, sum) && sum == 0) {
  10.             st.set(l, r, 1);
  11.             std::cout << "ACCEPTED" << std::endl;
  12.         } else std::cout << "REJECTED" << std::endl;
  13.     }
  14.     return 0;
  15. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-10-27 22:29:14 | 显示全部楼层
人造人 发表于 2021-10-25 10:49
main.cpp 改一下吧,改成这样

感谢大佬 我也搞清楚了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-26 00:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表