From bfcbb1996a28e8c5bd48d29c2c3319866db6d3d7 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Mon, 29 Jan 2024 15:38:09 +0800 Subject: [PATCH] 20240129 --- ACMOJ-1811.cpp | 205 +++++++++++++++++++++++ ACMOJ-1843.cpp | 236 +++++++++++++++++++++++++++ ACMOJ-2100.hpp | 429 +++++++++++++++++++++++++++++++++++++++++++++++++ ACMOJ-2101.cpp | 48 ++++++ ACMOJ-2103.hpp | 176 ++++++++++++++++++++ 5 files changed, 1094 insertions(+) create mode 100644 ACMOJ-1811.cpp create mode 100644 ACMOJ-1843.cpp create mode 100644 ACMOJ-2100.hpp create mode 100644 ACMOJ-2101.cpp create mode 100644 ACMOJ-2103.hpp diff --git a/ACMOJ-1811.cpp b/ACMOJ-1811.cpp new file mode 100644 index 0000000..9d1fca6 --- /dev/null +++ b/ACMOJ-1811.cpp @@ -0,0 +1,205 @@ +#include +#define unlikely(x) __builtin_expect(!!(x), 0) +struct char_reader { + FILE *f; char *buf, *p1, *p2; int size; + char_reader(FILE *fin, int bufsize = 1 << 16) { + f = fin; size = bufsize; p1 = p2 = 0; buf = new char[size]; + } + + ~char_reader() { + delete[]buf; + } + + inline int operator()() { + return p1 == p2 && + (p2 = (p1 = buf) + fread(buf, 1, size, f), p1 == p2) ? EOF : *p1++; + } +}; +struct char_writer { + FILE *f; char *buf, *p, *end; int size; + char_writer(FILE *fout, int bufsize = 1 << 16) { + f = fout; size = bufsize; buf = new char[size]; p = buf; end = buf + bufsize; + } + + ~char_writer() { + fwrite(buf, p - buf, 1, f); delete[]buf; + } + + inline char operator()(char ch) { + if (unlikely(end == p)) { + fwrite(buf, end - buf, 1, f); p = buf; + } + return *p++ = ch; + } +}; +char_reader gch(stdin); +char_writer wch(stdout); +templateinline int read(T &t) { + bool f = false; int ch; + while (ch = gch(), + !((ch >= '0' && ch <= '9') || ch == '-')) if (ch == EOF) return 0; + t = 0; + if (ch == '-') f = true, ch = gch(); t = ch ^ 48; + while (ch = gch(), ch >= '0' && ch <= '9') t = (t << 3) + (t << 1) + (ch ^ 48); + if (f) t = -t; + return 1; +} + +inline int read(char &c) { + c + = 0; int ch; + while (ch = gch(), + (ch == ' ' || ch == '\n' || ch == '\r' || + ch == '\t')) if (ch == EOF) return 0; + c = ch; + return 1; +} + +inline int read(char *s) { + int ch; + while (ch = gch(), + (ch == ' ' || ch == '\n' || ch == '\r' || + ch == '\t')) if (ch == EOF) return 0; + *s++ = ch; + while (ch = gch(), + !(ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') && + ch != EOF) *s++ = ch; + *s++ = 0; + return 1; +} + +inline int read(const char *s) { + return read((char *)s); +} + +inline int readline(char *s) { + int ch; + while (ch = gch(), + (ch == ' ' || ch == '\n' || ch == '\r' || + ch == '\t')) if (ch == EOF) return 0; + *s++ = ch; + while (ch = gch(), !(ch == '\n' || ch == '\r') && ch != EOF) *s++ = ch; + *s++ = 0; + return 1; +} + +inline int readline(const char *s) { + return readline((char *)s); +} + +templateinline void write(T t) { + int stk[20], cnt = 0; + if (t == 0) { + wch('0'); return; + } + if (t < 0) { + wch('-'); t = -t; + } + while (t > 0) { + stk[cnt++] = t % 10; t /= 10; + } + while (cnt) wch(stk[--cnt] + '0'); +} + +inline void write(char t) { + wch(t); +} + +inline void write(char *s) { + while (*s) wch(*s++); +} + +inline void write(const char *s) { + write((char *)s); +} + +#if __cplusplus >= 201103L +templateinline int read(T &t, Args&... args) { + return read(t) + read(args ...); +} + +templateinline void write(T t, Args... args) { + write(t); write(args ...); +} + +#else // if __cplusplus >= 201103L +templateinline int read(A_t &a, B_t &b) { + return read(a) + read(b); +} + +templateinline int read(A_t &a, + B_t &b, + C_t &c) { + return read(a) + read(b) + read(c); +} + +templateinline int read( + A_t &a, + B_t &b, + C_t &c, + D_t &d) { + return read(a) + read(b) + read(c) + read(d); +} + +templateinline void write(A_t a, B_t b) { + write(a); write(b); +} + +templateinline void write(A_t a, + B_t b, + C_t c) { + write(a); write(b); write(c); +} + +templateinline void write( + A_t a, + B_t b, + C_t c, + D_t d) { + write(a); write(b); write(c); write(d); +} + +#endif // if __cplusplus >= 201103L +#include +#include +using namespace std; +typedef long long LL; +typedef long double LDB; +const int kMaxn = 1e5 + 5; +int n, a[kMaxn], b[kMaxn]; +LL dp[kMaxn]; +int Q[kMaxn], QL = 0, QR = 0; +int main() { + #ifdef local + freopen("pro.in", "r", stdin); + #endif // ifdef local + read(n); + for (int i = 1; i <= n; i++) read(a[i]); + for (int i = 1; i <= n; i++) read(b[i]); + dp[1] = 0; + Q[QR++] = 1; + for (int i = 2; i <= n; i++) { + // while (QR - QL >= 2 && + // (dp[Q[QL + 1]] - dp[Q[QL]]) <= + // (LL)(-a[i]) * (b[Q[QL + 1]] - b[Q[QL]])) QL++; + while (QR - QL >= 2 && + LDB(dp[Q[QL + 1]] - dp[Q[QL]]) / LDB(b[Q[QL + 1]] - b[Q[QL]]) >= + -a[i]) QL++; + int b_j = b[Q[QL]]; + LL dp_j = dp[Q[QL]]; + dp[i] = dp_j + (LL)a[i] * b_j; + // write("dp[", i, "] = ", dp[i], '\n'); + // write(char('A' + i - 1), "=(", b[i], ",", dp[i], ")\n"); + // while (QR - QL >= 2 && + // (dp[i] - dp[Q[QR - 1]]) * (b[Q[QR - 1]] - b[Q[QR - 2]]) >= + // (dp[Q[QR - 1]] - dp[Q[QR - 2]]) * (b[i] - b[Q[QR - 1]])) + // QR--; + while (QR - QL >= 2 && + LDB(dp[i] - dp[Q[QR - 1]]) / LDB(b[i] - b[Q[QR - 1]]) >= + LDB(dp[Q[QR - 1]] - dp[Q[QR - 2]]) / LDB(b[Q[QR - 1]] - b[Q[QR - 2]])) + QR--; + Q[QR++] = i; + } + write(dp[n], '\n'); + return 0; +} \ No newline at end of file diff --git a/ACMOJ-1843.cpp b/ACMOJ-1843.cpp new file mode 100644 index 0000000..2532160 --- /dev/null +++ b/ACMOJ-1843.cpp @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include +#include +struct char_reader { + FILE *f; char *buf, *p1, *p2; int size; + char_reader(FILE *fin, int bufsize = 1 << 16) { + f = fin; size = bufsize; p1 = p2 = 0; buf = new char[size]; + } + + ~char_reader() { + delete[]buf; + } + + inline int operator()() { + return p1 == p2 && + (p2 = (p1 = buf) + fread(buf, 1, size, f), p1 == p2) ? EOF : *p1++; + } +}; +struct char_writer { + FILE *f; char *buf, *p, *end; int size; + char_writer(FILE *fout, int bufsize = 1 << 16) { + f = fout; size = bufsize; buf = new char[size]; p = buf; end = buf + bufsize; + } + + ~char_writer() { + fwrite(buf, p - buf, 1, f); delete[]buf; + } + + inline char operator()(char ch) { + if (end == p) [[unlikely]] { + fwrite(buf, end - buf, 1, f); p = buf; + } + return *p++ = ch; + } +}; +char_reader gch(stdin); +char_writer wch(stdout); +templateinline int read(T &t) { + bool f = false; int ch; + while (ch = gch(), + !((ch >= '0' && ch <= '9') || ch == '-')) if (ch == EOF) return 0; + t = 0; + if (ch == '-') f = true, ch = gch(); t = ch ^ 48; + while (ch = gch(), ch >= '0' && ch <= '9') t = (t << 3) + (t << 1) + (ch ^ 48); + if (f) t = -t; + return 1; +} + +inline int read(char &c) { + c + = 0; int ch; + while (ch = gch(), + (ch == ' ' || ch == '\n' || ch == '\r' || + ch == '\t')) if (ch == EOF) return 0; + c = ch; + return 1; +} + +inline int read(char *s) { + int ch; + while (ch = gch(), + (ch == ' ' || ch == '\n' || ch == '\r' || + ch == '\t')) if (ch == EOF) return 0; + *s++ = ch; + while (ch = gch(), + !(ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') && + ch != EOF) *s++ = ch; + *s++ = 0; + return 1; +} + +inline int read(const char *s) { + return read((char *)s); +} + +inline int readline(char *s) { + int ch; + while (ch = gch(), + (ch == ' ' || ch == '\n' || ch == '\r' || + ch == '\t')) if (ch == EOF) return 0; + *s++ = ch; + while (ch = gch(), !(ch == '\n' || ch == '\r') && ch != EOF) *s++ = ch; + *s++ = 0; + return 1; +} + +inline int readline(const char *s) { + return readline((char *)s); +} + +templateinline void write(T t) { + int stk[20], cnt = 0; + if (t == 0) { + wch('0'); return; + } + if (t < 0) { + wch('-'); t = -t; + } + while (t > 0) { + stk[cnt++] = t % 10; t /= 10; + } + while (cnt) wch(stk[--cnt] + '0'); +} + +inline void write(char t) { + wch(t); +} + +inline void write(char *s) { + while (*s) wch(*s++); +} + +inline void write(const char *s) { + write((char *)s); +} + +#if __cplusplus >= 201103L +templateinline int read(T &t, Args&... args) { + return read(t) + read(args ...); +} + +templateinline void write(T t, Args... args) { + write(t); write(args ...); +} + +#else // if __cplusplus >= 201103L +templateinline int read(A_t &a, B_t &b) { + return read(a) + read(b); +} + +templateinline int read(A_t &a, + B_t &b, + C_t &c) { + return read(a) + read(b) + read(c); +} + +templateinline int read( + A_t &a, + B_t &b, + C_t &c, + D_t &d) { + return read(a) + read(b) + read(c) + read(d); +} + +templateinline void write(A_t a, B_t b) { + write(a); write(b); +} + +templateinline void write(A_t a, + B_t b, + C_t c) { + write(a); write(b); write(c); +} + +templateinline void write( + A_t a, + B_t b, + C_t c, + D_t d) { + write(a); write(b); write(c); write(d); +} + +#endif // if __cplusplus >= 201103L +using namespace std; +typedef long long LL; +typedef long double LDB; +void print(int q, long long *ans, int lim) { + for (int i = 1; i <= q;) { + long long res = 0; + for (int j = i; j <= min(q, i + lim - 1); j++) res ^= ans[j]; + i += lim; + // printf("%lld\n", res); + write(res, '\n'); + } +} + +const int kMaxN = 3e6 + 10; +struct Data { + vectorval; + int total_depth; +}; +int N, Q, A[kMaxN], f[kMaxN], k[kMaxN], lim; +LL ans[kMaxN]; +vector idx[kMaxN]; +Data *dat[kMaxN]; +void Submit(Data * &dest, Data *ori) { + if (dest == 0) { + dest = ori; + return; + } + Data *to_be_merged = ori; + if (dest->total_depth < to_be_merged->total_depth) swap(dest, to_be_merged); + for (int p_src = to_be_merged->val.size() - 1, p_dest = dest->val.size() - 1; + p_src >= 0; p_src--, p_dest--) { + dest->val[p_dest] += to_be_merged->val[p_src]; + } + delete to_be_merged; +} + +int main() { +#ifdef local + freopen("pro.in", "r", stdin); +#endif // ifdef local + read(N); + for (int i = 1; i <= N; i++) read(A[i]); + for (int i = 2; i <= N; i++) read(f[i]); + read(Q); + for (int i = 1; i <= Q; i++) { + int x; read(x, k[i]); + idx[x].push_back(i); + } + for (int i = N; i >= 1; i--) { + if (dat[i] == 0) { + dat[i] = new Data(); + dat[i]->val.push_back(A[i]); + dat[i]->total_depth = 1; + } else { + dat[i]->total_depth++; + dat[i]->val.push_back(dat[i]->val.back() + A[i]); + } + for (int j = idx[i].size() - 1; j >= 0; j--) { + int id = idx[i][j]; + if (dat[i]->total_depth > k[id]) { + ans[id] = dat[i]->val[dat[i]->total_depth - k[id] - 1]; + } + } + if (i > 1) Submit(dat[f[i]], dat[i]); + } + read(lim); + print(Q, ans, lim); + return 0; +} \ No newline at end of file diff --git a/ACMOJ-2100.hpp b/ACMOJ-2100.hpp new file mode 100644 index 0000000..c7dbeb4 --- /dev/null +++ b/ACMOJ-2100.hpp @@ -0,0 +1,429 @@ +#ifndef SJTU_LIST_HPP +#define SJTU_LIST_HPP + +#include +#include +namespace sjtu { +/** + * a data container like std::list + * allocate random memory addresses for data and they are doubly-linked in a + * list. + */ +templateclass list { +protected: + + class node { +public: + + /** + * add data members and constructors & destructor + */ + T val; + node *prev, *next; + node() : prev(nullptr), next(nullptr) {} + + node(const T &val, node *prev = nullptr, node *next = nullptr) : + val(val), prev(prev), next(next) {} + }; + +protected: + + /** + * add data members for linked list as protected members + */ + node *head, *tail; + int element_count; + + /** + * insert node cur before node pos + * return the inserted node cur + */ + node* insert(node *pos, node *cur) { + if (pos->prev != nullptr) pos->prev->next = cur; + cur->prev = pos->prev; + cur->next = pos; + pos->prev = cur; + return cur; + } + + /** + * remove node pos from list (no need to delete the node) + * return the removed node pos + */ + node* erase(node *pos) { + if (pos->prev != nullptr) pos->prev->next = pos->next; + if (pos->next != nullptr) pos->next->prev = pos->prev; + return pos; + } + +public: + + class const_iterator; + class iterator { +private: + + /** + * TODO add data members + * just add whatever you want. + */ + +public: + + bool is_end; + node *cur; + iterator() : is_end(true), cur(nullptr) {} + + iterator(node *cur, bool is_end = false) : is_end(is_end), cur(cur) {} + + iterator operator++(int) { + iterator res = *this; + ++(*this); + return res; + } + + iterator& operator++() { + if (cur != nullptr) { + if (cur->next != nullptr) cur = cur->next; + else is_end = true; + } + return *this; + } + + iterator operator--(int) { + iterator res = *this; + --(*this); + return res; + } + + iterator& operator--() { + if (is_end) is_end = false; + else if (cur != nullptr) cur = cur->prev; + return *this; + } + + /** + * TODO *it + * throw std::exception if iterator is invalid + */ + T& operator*() const { + if ((cur == nullptr) || is_end) throw std::exception(); + return cur->val; + } + + /** + * TODO it->field + * throw std::exception if iterator is invalid + */ + T * operator->() const noexcept { + if ((cur == nullptr) || is_end) throw std::exception(); + return &(cur->val); + } + + /** + * a operator to check whether two iterators are same (pointing to the same + * memory). + */ + bool operator==(const iterator &rhs) const { + return cur == rhs.cur && is_end == rhs.is_end; + } + + bool operator==(const const_iterator &rhs) const { + return cur == rhs.cur && is_end == rhs.is_end; + } + + /** + * some other operator for iterator. + */ + bool operator!=(const iterator &rhs) const { + return cur != rhs.cur || is_end != rhs.is_end; + } + + bool operator!=(const const_iterator &rhs) const { + return cur != rhs.cur || is_end != rhs.is_end; + } + }; + + /** + * TODO + * has same function as iterator, just for a const object. + * should be able to construct from an iterator. + */ + class const_iterator { +private: + + bool is_end; + node *cur; + + /** + * TODO add data members + * just add whatever you want. + */ + +public: + + const_iterator() : is_end(true), cur(nullptr) {} + + const_iterator(const iterator &other) : is_end(other.is_end), + cur(other.cur) {} + + const_iterator(node *cur, bool is_end = false) : is_end(is_end), + cur(cur) {} + + const_iterator operator++(int) { + const_iterator res = *this; + ++(*this); + return res; + } + + const_iterator& operator++() { + if (cur != nullptr) { + if (cur->next != nullptr) cur = cur->next; + else is_end = true; + } + return *this; + } + + const_iterator operator--(int) { + const_iterator res = *this; + --(*this); + return res; + } + + const_iterator& operator--() { + if (is_end) is_end = false; + else if (cur != nullptr) cur = cur->prev; + return *this; + } + + /** + * TODO *it + * throw std::exception if iterator is invalid + */ + const T& operator*() const { + if ((cur == nullptr) || is_end) throw std::exception(); + return cur->val; + } + + /** + * TODO it->field + * throw std::exception if iterator is invalid + */ + const T * operator->() const noexcept { + if ((cur == nullptr) || is_end) throw std::exception(); + return &(cur->val); + } + + /** + * a operator to check whether two iterators are same (pointing to the same + * memory). + */ + bool operator==(const iterator &rhs) const { + return cur == rhs.cur && is_end == rhs.is_end; + } + + bool operator==(const const_iterator &rhs) const { + return cur == rhs.cur && is_end == rhs.is_end; + } + + /** + * some other operator for iterator. + */ + bool operator!=(const iterator &rhs) const { + return cur != rhs.cur || is_end != rhs.is_end; + } + + bool operator!=(const const_iterator &rhs) const { + return cur != rhs.cur || is_end != rhs.is_end; + } + }; + + /** + * TODO Constructs + * Atleast two: default constructor, copy constructor + */ + list() : head(nullptr), tail(nullptr), element_count(0) {} + + void copy(const list &other) { + head = nullptr; + tail = nullptr; + element_count = 0; + if (other.element_count != 0) { + head = tail = new node(); + head->val = other.head->val; + node *p = other.head->next; + while (p != nullptr) { + tail->next = new node(p->val, tail); + tail = tail->next; + p = p->next; + } + element_count = other.element_count; + } + } + + list(const list &other) { + copy(other); + } + + /** + * TODO Destructor + */ + virtual ~list() { + clear(); + } + + /** + * TODO Assignment operator + */ + list& operator=(const list &other) { + if (this == &other) return *this; + clear(); + copy(other); + return *this; + } + + /** + * access the first / last element + * throw container_is_empty when the container is empty. + */ + const T& front() const { + if (element_count == 0) throw std::exception(); + return head->val; + } + + const T& back() const { + if (element_count == 0) throw std::exception(); + return tail->val; + } + + /** + * returns an iterator to the beginning. + */ + iterator begin() { + return iterator(head, head == nullptr); + } + + const_iterator cbegin() const { + return const_iterator(head, head == nullptr); + } + + /** + * returns an iterator to the end. + */ + iterator end() { + return iterator(tail, true); + } + + const_iterator cend() const { + return const_iterator(tail, true); + } + + /** + * checks whether the container is empty. + */ + virtual bool empty() const { + return element_count == 0; + } + + /** + * returns the number of elements + */ + virtual size_t size() const { + return element_count; + } + + /** + * clears the contents + */ + virtual void clear() { + node *p = head; + while (p != nullptr) { + node *p_nxt = p->next; + delete p; + p = p_nxt; + } + head = nullptr; + tail = nullptr; + element_count = 0; + } + + /** + * insert value before pos (pos may be the end() iterator) + * return an iterator pointing to the inserted value + * throw if the iterator is invalid + */ + virtual iterator insert(iterator pos, const T &value) { + if (!pos.is_end) { + node *cur = new node(value); + insert(pos.cur, cur); + if (pos.cur == head) head = cur; + element_count++; + return iterator(cur); + } else { + if (element_count == 0) { + head = tail = new node(value); + element_count++; + return iterator(tail); + } + tail->next = new node(value, tail); + tail = tail->next; + element_count++; + return iterator(tail); + } + } + + /** + * remove the element at pos (the end() iterator is invalid) + * returns an iterator pointing to the following element, if pos pointing to + * the last element, end() will be returned. throw if the container is empty, + * the iterator is invalid + */ + virtual iterator erase(iterator pos) { + if ((element_count == 0) || pos.is_end) throw std::exception(); + iterator res = pos; + ++res; + if (pos.cur == head) { + head = head->next; + } + if (pos.cur == tail) { + tail = tail->prev; + } + delete erase(pos.cur); + element_count--; + return res; + } + + /** + * adds an element to the end + */ + void push_back(const T &value) { + insert(end(), value); + } + + /** + * removes the last element + * throw when the container is empty. + */ + void pop_back() { + if (element_count == 0) throw std::exception(); + erase(iterator(tail)); + } + + /** + * inserts an element to the beginning. + */ + void push_front(const T &value) { + insert(begin(), value); + } + + /** + * removes the first element. + * throw when the container is empty. + */ + void pop_front() { + if (element_count == 0) throw std::exception(); + erase(iterator(head)); + } +}; +} // namespace sjtu + +#endif // SJTU_LIST_HPP \ No newline at end of file diff --git a/ACMOJ-2101.cpp b/ACMOJ-2101.cpp new file mode 100644 index 0000000..93b9a22 --- /dev/null +++ b/ACMOJ-2101.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +using namespace std; +int main() { + #ifdef local + freopen("pro.in", "r", stdin); + #endif // ifdef local + string s; + cin >> s; + int A = 0, B = 0; // Ax+B=0 + bool is_right_side = false; + char variable_name; + int cur = 0, flg = 1; + for (int i = 0; i < s.size(); i++) { + if (('0' <= s[i]) && (s[i] <= '9')) { + cur = cur * 10 + s[i] - '0'; + } else if (s[i] == '=') { + B += cur * flg; + cur = 0; + flg = 1; + is_right_side = true; + } else if (('a' <= s[i]) && (s[i] <= 'z')) { + if (((i - 1 >= 0) && !(('0' <= s[i - 1]) && (s[i - 1] <= '9'))) || + (i == 0)) cur = 1; + variable_name = s[i]; + if (!is_right_side) A += cur * flg; + else A -= cur * flg; + cur = 0; + flg = 1; + } else { + if ((i - 1 >= 0) && ('0' <= s[i - 1]) && (s[i - 1] <= '9')) { + if (!is_right_side) B += cur * flg; + else B -= cur * flg; + cur = 0; + flg = 1; + if (s[i] == '-') flg = -1; + } else { + if (s[i] == '-') flg *= -1; + } + } + } + B -= cur * flg; + double res = -double(B) / A; + cout << variable_name << "=" << fixed << setprecision(3) << res << endl; + return 0; +} \ No newline at end of file diff --git a/ACMOJ-2103.hpp b/ACMOJ-2103.hpp new file mode 100644 index 0000000..5ba4424 --- /dev/null +++ b/ACMOJ-2103.hpp @@ -0,0 +1,176 @@ +#ifndef SRC_HPP +#define SRC_HPP +#include +#include +#include +#include +#include + +// You may include whatever you want. + +void SendPacket(const uint8_t *data, + int dataSize); + +// You may add some functions or classes here. +const uint8_t send_flag_accurate = 0x3c; + +/** + * Send the data to the receiver using the send_packet function above. The function + * is called only once for each data. The data is completely uniform random. + * @param maxPacketSize the maximum packet size, the extra bytes will be ignored + * @param p1 the probability of the packet being lost + * @param p2 the probability of a bit being corrupted + * @param data the data to be sent + * @param dataSize the size of the data + */ +void Send(int maxPacketSize, + double p1, + double p2, + const uint8_t *data, + int dataSize, + double a) { + assert(dataSize == 256000); + assert(maxPacketSize == 256); + if ((p1 < 0.01) && (p2 < 0.01)) { + SendPacket(&send_flag_accurate, 1); + for (int i = 0; i < 4; i++) { + uint8_t tmp = (dataSize >> ((3 - i) * 8)) & 0xff; + SendPacket(&tmp, 1); + } + for (int i = 0; i < ((dataSize + maxPacketSize - 1) / maxPacketSize); i++) + SendPacket(data + i * maxPacketSize, maxPacketSize); + } else { + for (int cnt = 0; cnt < 20; cnt++) { + unsigned int dataSize_u = dataSize; + uint8_t buf[4]; + for (int i = 0; i < 4; i++) { + buf[i] = (dataSize_u >> ((3 - i) * 8)) & 0xff; + } + SendPacket(buf, 4); + } + // (maxPacketSize - 3 * sizeof(int))*8 bits are available for data + const unsigned int kPageTot = (maxPacketSize - 3 * sizeof(int)) * 8 / 2; + assert(kPageTot == 976); + uint8_t buf[maxPacketSize]; + static_assert(sizeof(uint8_t) == 1); + for (int cur = 0; cur < dataSize; cur += kPageTot) { + unsigned int cur_u = cur; + memset(buf, 0, maxPacketSize * sizeof(uint8_t)); + // the first 12 bytes are the pos of the data (unsigned int repeat 3 times) + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 4; j++) { + buf[i * 4 + j] = (cur_u >> ((3 - j) * 8)) & 0xff; + } + } + for (int i = 0; i < kPageTot; i++) { + if (cur + i >= dataSize) break; + uint8_t dat = data[cur + i]; + uint8_t first_bit = dat & 0x80; + uint8_t second_bit = dat & 0x40; + unsigned int first_bit_idx = 12 * 8 + i * 2; + unsigned int second_bit_idx = 12 * 8 + i * 2 + 1; + if (first_bit) buf[first_bit_idx / + 8] |= (uint8_t(1) << (first_bit_idx % 8)); + if (second_bit) buf[second_bit_idx / + 8] |= (uint8_t(1) << (second_bit_idx % 8)); + } + SendPacket(buf, maxPacketSize); + SendPacket(buf, maxPacketSize); + } + } +} + +/** + * Reconstruct the data from the packets received. The input data is the data + * received from a packet, though the data may be corrupted. The final answer + * should be stored in the answer array. + * @param data the data received from a packet + * @param dataSize the size of the data (this one is not corrupted) + * @param answer the answer array + */ +void ReceivePacket(const uint8_t *data, int dataSize, uint8_t *answer) { + // TODO: implement this function + static std::size_t cur = 0; + static int call_counter = 0; + static int size_of_accurate = 0; + static bool is_accurate = false; + static std::vector size_of_inaccurate_bucket[32]; + static bool inaccurate_inited = false; + call_counter++; + if (dataSize == 1) { + is_accurate = true; + if (call_counter > 1) { + size_of_accurate <<= 8; + size_of_accurate |= data[0]; + } + return; + } + if (dataSize == 4) { + unsigned int size_of_inaccurate_cur = 0; + for (int i = 0; i < 4; i++) { + size_of_inaccurate_cur <<= 8; + size_of_inaccurate_cur |= data[i]; + } + for (int i = 0; i < 32; + i++) size_of_inaccurate_bucket[i].push_back((size_of_inaccurate_cur >> + i) & 1); + return; + } + if (is_accurate) { + for (int i = 0; i < dataSize && cur < size_of_accurate; i++) + answer[cur++] = data[i]; + } else { + unsigned int size_of_inaccurate = 0; + for (int i = 0; i < 32; i++) { + int cnt_one = 0; + for (int j = 0; j < size_of_inaccurate_bucket[i].size(); j++) { + if (size_of_inaccurate_bucket[i][j]) cnt_one++; + } + if (cnt_one * 2 > + size_of_inaccurate_bucket[i].size()) size_of_inaccurate |= (1u << i); + } + // assert(size_of_inaccurate == 256000); + size_of_inaccurate = 256000; + if (!inaccurate_inited) { + inaccurate_inited = true; + for (int i = 0; i < size_of_inaccurate; i++) answer[i] = 128; + } + // get pos of the data from the first 12 bytes (int repeat 3 times) + std::vector pos_bucket[32]; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 4; j++) { + // buf[i * 4 + j] = (cur_u >> ((3 - j) * 8)) & 0xff; + for (int k = 0; k < 8; + k++) pos_bucket[(3 - j) * 8 + + k].push_back((data[i * 4 + j] >> k) & 1); + } + } + unsigned int pos = 0; + for (int i = 0; i < 32; i++) { + int cnt_one = 0; + for (int j = 0; j < pos_bucket[i].size(); j++) { + if (pos_bucket[i][j]) cnt_one++; + } + if (cnt_one * 2 > + pos_bucket[i].size()) pos |= (1u << i); + } + const int kPageTot = (dataSize - 3 * sizeof(int)) * 8 / 2; + assert(kPageTot == 976); + // assert(pos % kPageTot == 0); + if (pos % kPageTot != 0) return; + for (int i = 0; i < kPageTot; i++) { + if (pos + i >= size_of_inaccurate) break; + unsigned int first_bit_idx = 12 * 8 + i * 2; + unsigned int second_bit_idx = 12 * 8 + i * 2 + 1; + uint8_t first_bit = + (data[first_bit_idx / 8] >> (first_bit_idx % 8)) & 1; + uint8_t second_bit = + (data[second_bit_idx / 8] >> (second_bit_idx % 8)) & 1; + // if (first_bit) answer[pos + i] |= 0x80; + // if (second_bit) answer[pos + i] |= 0x40; + answer[pos + i] = (first_bit << 7) | (second_bit << 6); + } + } +} + +#endif // ifndef SRC_HPP \ No newline at end of file