You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

380 lines
10 KiB

  1. #include <algorithm>
  2. #include <chrono>
  3. #include <deque>
  4. #include <functional>
  5. #include <iomanip>
  6. #include <iostream>
  7. #include <list>
  8. #include <map>
  9. #include <sstream>
  10. #include <vector>
  11. class Date {
  12. std::string date;
  13. int year, month, day, total;
  14. void dateToInt() {
  15. year = stoi(date.substr(0, 4));
  16. month = stoi(date.substr(5, 2));
  17. day = stoi(date.substr(8, 2));
  18. total = year * 400 + month * 31 + day;
  19. }
  20. public:
  21. Date() {
  22. date = "1970-01-01";
  23. dateToInt();
  24. }
  25. explicit Date(const std::string& d) {
  26. date = d;
  27. dateToInt();
  28. }
  29. Date(const Date& d) {
  30. date = d.date, year = d.year, month = d.month, day = d.day,
  31. total = d.total;
  32. }
  33. Date(Date&& d) {
  34. date = std::move(d.date);
  35. year = d.year, month = d.month, day = d.day, total = d.total;
  36. }
  37. Date& operator=(Date d) {
  38. date = d.date, year = d.year, month = d.month, day = d.day,
  39. total = d.total;
  40. return *this;
  41. }
  42. bool isLeap(int year) {
  43. if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) return true;
  44. return false;
  45. }
  46. int maxDay(int month, int year) {
  47. switch (month) {
  48. case 4:
  49. case 6:
  50. case 9:
  51. case 11:
  52. return 30;
  53. break;
  54. case 2:
  55. return (isLeap(year) ? 29 : 28);
  56. break;
  57. default:
  58. return 31;
  59. }
  60. }
  61. std::string getDate() const { return date; }
  62. int getTotal() const { return total; }
  63. void goNextDay() {
  64. day++;
  65. if (day > maxDay(month, year)) day = 1, month++;
  66. if (month > 12) month = 1, year++;
  67. total = year * 400 + month * 31 + day;
  68. std::stringstream yearss, monthss, dayss;
  69. yearss << std::setfill('0') << std::setw(4) << year;
  70. monthss << std::setfill('0') << std::setw(2) << month;
  71. dayss << std::setfill('0') << std::setw(2) << day;
  72. date = yearss.str() + "-" + monthss.str() + "-" + dayss.str();
  73. }
  74. // prefix ++ operator for getting the next day
  75. Date& operator++() {
  76. goNextDay();
  77. return *this;
  78. }
  79. Date operator++(int) {
  80. Date res(*this);
  81. goNextDay();
  82. return res;
  83. }
  84. operator int() const { return total; }
  85. bool operator<(const Date& d) { return (total < d.total); }
  86. bool operator>(const Date& d) { return (total > d.total); }
  87. bool operator<=(const Date& d) { return (total <= d.total); }
  88. bool operator>=(const Date& d) { return (total >= d.total); }
  89. bool operator==(const Date& d) { return (total == d.total); }
  90. friend std::ostream& operator<<(std::ostream& os, const Date& dt);
  91. };
  92. std::ostream& operator<<(std::ostream& os, const Date& dt) {
  93. os << dt.getDate();
  94. return os;
  95. }
  96. class Transaction {
  97. public:
  98. Date date;
  99. double money;
  100. operator int() { return int(date); }
  101. };
  102. template <typename K, typename V>
  103. class Btree;
  104. template <typename K, typename V>
  105. class TreeNode {
  106. std::pair<K, V>* m_data;
  107. int m_n, m_t; // current number of keys, and the maximum number of keys
  108. TreeNode<K, V>** m_c; // children
  109. bool m_leaf; // is true if the node is a leaf
  110. TreeNode<K, V>(int t, bool leaf) : m_n(0), m_t(t), m_leaf(leaf) {
  111. m_data = new std::pair<K, V>[2 * t];
  112. m_c = new TreeNode<K, V>*[2 * t];
  113. }
  114. ~TreeNode<K, V>() {
  115. delete[] m_data;
  116. if (!m_leaf && m_n > 0)
  117. for (int i = 0; i <= m_n; ++i) delete m_c[i];
  118. delete[] m_c;
  119. }
  120. // Insert a new key in the subtree. Assumption: node must be non-full
  121. void insert(K key, V value) {
  122. int i = m_n - 1; // last child
  123. if (m_leaf) {
  124. // move all greater keys one position right and find the location of
  125. // a new key
  126. while (i >= 0 && m_data[i].first > key) {
  127. m_data[i + 1] = m_data[i];
  128. i--;
  129. }
  130. m_data[i + 1] = {key, value};
  131. m_n++;
  132. } else {
  133. // Find the child which is going to have the new key
  134. while (i >= 0 && m_data[i].first > key) i--;
  135. // if the child is full
  136. if (m_c[i + 1]->m_n == 2 * m_t - 1) {
  137. splitChild(i + 1, m_c[i + 1]);
  138. if (m_data[i + 1].first < key) i++;
  139. }
  140. m_c[i + 1]->insert(key, value);
  141. }
  142. }
  143. // split the child 'child' of this node. Assumption: child must be full
  144. void splitChild(int i, TreeNode<K, V>* child) {
  145. TreeNode<K, V>* temp = new TreeNode<K, V>(child->m_t, child->m_leaf);
  146. temp->m_n = m_t - 1;
  147. for (int j = 0; j < m_t - 1; j++)
  148. temp->m_data[j] = child->m_data[j + m_t];
  149. if (!child->m_leaf) {
  150. for (int j = 0; j < m_t; j++) temp->m_c[j] = child->m_c[j + m_t];
  151. }
  152. child->m_n = m_t - 1;
  153. for (int j = m_n; j >= i + 1; --j) m_c[j + 1] = m_c[j];
  154. m_c[i + 1] = temp;
  155. for (int j = m_n - 1; j >= i; --j) m_data[j + 1] = m_data[j];
  156. m_data[i] = child->m_data[m_t - 1];
  157. m_n++;
  158. }
  159. void traverse() {
  160. for (int i = 0; i < m_n; i++) {
  161. if (!m_leaf) m_c[i]->traverse();
  162. std::cout << m_data[i].first << ' ' << m_data[i].second << ' ';
  163. }
  164. if (!m_leaf) m_c[m_n]->traverse();
  165. std::cout << '\n';
  166. }
  167. // recursive search O(logn)
  168. const TreeNode<K, V>* search(K key) const {
  169. int i = 0;
  170. while (i < m_n && m_data[i].first < key) i++;
  171. if (m_data[i].first == key) return this;
  172. if (m_leaf == true) return NULL;
  173. return m_c[i]->search(key);
  174. }
  175. // range query
  176. std::list<V> search(const K& from, const K& to) const {
  177. std::list<V> res;
  178. if (m_leaf) {
  179. for (int i = 0; i < m_n; ++i) {
  180. if (m_data[i].first >= from && m_data[i].first <= to)
  181. res.push_back(m_data[i].second);
  182. }
  183. } else {
  184. if (m_data[0].first >= from) {
  185. res.splice(res.end(), m_c[0]->search(from, to));
  186. if (m_data[0].first >= from && m_data[0].first <= to)
  187. res.push_back(m_data[0].second);
  188. }
  189. K prev = m_data[0].first;
  190. for (int i = 1; i < m_n; ++i) {
  191. if (prev > to) break;
  192. if (m_data[i].first >= from) {
  193. res.splice(res.end(), m_c[i]->search(from, to));
  194. }
  195. if (m_data[i].first >= from && m_data[i].first <= to)
  196. res.push_back(m_data[i].second);
  197. prev = m_data[i].first;
  198. }
  199. if (prev <= to) {
  200. res.splice(res.end(), m_c[m_n]->search(from, to));
  201. }
  202. }
  203. return res;
  204. }
  205. friend class Btree<K, V>;
  206. };
  207. template <typename K, typename V>
  208. class IRangeMap {
  209. virtual int size() const = 0;
  210. virtual bool isEmpty() const = 0;
  211. virtual void add(const K& key, const V& value) = 0;
  212. virtual bool contains(const K& key) const = 0;
  213. virtual V& lookup(const K& key) const = 0;
  214. virtual std::list<V> lookupRange(const K& from, const K& to) const = 0;
  215. };
  216. template <typename K, typename V>
  217. class Btree : IRangeMap<K, V> {
  218. TreeNode<K, V>* m_root;
  219. int m_sz, m_t;
  220. public:
  221. explicit Btree(int t) : m_root(nullptr), m_sz(0), m_t(t) {}
  222. ~Btree<K, V>() { delete m_root; }
  223. // search a key in the tree. Returns a pointer to a TreeNode which has the
  224. // key.
  225. const TreeNode<K, V>* search(const K& key) const {
  226. return (m_root == NULL) ? NULL : m_root->search(key);
  227. }
  228. // Return the value of the key. Assumption: key exists in the tree
  229. V& lookup(const K& key) const {
  230. const auto it = search(key);
  231. if (it == NULL) throw "key doesn't exist!";
  232. for (int i = 0; i < m_t * 2 - 1; ++i)
  233. if (it->m_data[i].first == key) return it->m_data[i].second;
  234. throw "key doesn't exist!";
  235. }
  236. bool contains(const K& key) const { return (search(key) != NULL); }
  237. std::list<V> lookupRange(const K& from, const K& to) const {
  238. if (m_root == NULL) return std::list<V>();
  239. return m_root->search(from, to);
  240. }
  241. void traverse() {
  242. if (m_root) m_root->traverse();
  243. }
  244. void add(const K& key, const V& value) {
  245. if (key == Date("2021-11-11")) {
  246. Date d = Date("2021-11-11");
  247. }
  248. if (m_root == NULL) {
  249. m_root = new TreeNode<K, V>(m_t, true);
  250. m_root->m_data[0] = {key, value};
  251. m_root->m_n = 1;
  252. } else {
  253. // if root is full
  254. if (m_root->m_n == m_t * 2 - 1) {
  255. TreeNode<K, V>* temp = new TreeNode<K, V>(m_t, false);
  256. // rearrange root and its child
  257. temp->m_c[0] = m_root;
  258. // split the old root
  259. temp->splitChild(0, m_root);
  260. int i = 0;
  261. if (temp->m_data[0].first < key) i++;
  262. temp->m_c[i]->insert(key, value);
  263. m_root = temp;
  264. } else
  265. m_root->insert(key, value);
  266. }
  267. m_sz++;
  268. }
  269. int size() const { return m_sz; }
  270. bool isEmpty() const { return (m_sz == 0); }
  271. };
  272. int main() {
  273. #ifdef DEBUG
  274. freopen("test", "r", stdin);
  275. #endif
  276. int n;
  277. std::cin >> n;
  278. Btree<Date, double> map(2);
  279. //std::map<Date, double> mp;
  280. for (int i = 0; i < n; ++i) {
  281. std::string datestr, type;
  282. double money;
  283. std::cin >> datestr;
  284. if (datestr == "REPORT") {
  285. std::string from, to;
  286. std::cin >> type >> from >> type >> to;
  287. std::list<double> l = map.lookupRange(Date(from), Date(to));
  288. double ans = 0, ans2 = 0;
  289. for (const auto& it : l) ans += it;
  290. /*
  291. auto itfrom = mp.lower_bound(Date(from)),
  292. itto = mp.upper_bound(Date(to));
  293. for (auto it = itfrom; it != itto; ++it) {
  294. ans2 += it->second;
  295. std::cout << it->first << ' ' << it->second << '\n';
  296. }
  297. */
  298. std::cout << ans << '\n';
  299. } else {
  300. std::cin >> type >> money;
  301. if (type == "WITHDRAW") money *= -1;
  302. Date d(datestr);
  303. //mp[d] += money;
  304. if (map.contains(d)) {
  305. map.lookup(d) += money;
  306. } else {
  307. map.add(Date(datestr), money);
  308. }
  309. }
  310. }
  311. #ifdef DEBUG
  312. #endif
  313. }