1 solutions
-
0
注意一下本题当中提到的关键信息 : ,这意味着我们可以将所有的直线变成至多 个整点来存储(因为不需要考虑线段两端的端点,所以每个线段的点数是 个)。由于 ,所以复杂度的上限是 ,而且根本跑不满。
然后我们利用两个
unordered_map
套map
来存储上面这些整点。每次传入起点坐标和方向之后,利用upper_bound
和prev(lower_bound)
找到其对应打到的镜面(也就是 两个方向的前驱和后继,需要注意处理空容器或前驱后继不存在等极端情况)。只要光线强度小于 ,或者剩余时间为 就要停机。此外,当前方向没有镜面,或者当前剩余时间泡不到镜面时,也要直接返回结果,此时结果需要单独计算,需要注意一下浮点数转整数时是否可能带来误差(例如
5.9999999995
向下类型转成5
这样的情况)。此外,我们除了维护离散的点之外,还需要维护这些点对应的镜面编号是多少,在碰撞时还需要维护其打向镜面的坐标、方向、碰撞时间。这样才能完整维护上面的对应信息。
// feature \sum |x_1 - x_2| <= 300000 #include <stdio.h> #include <algorithm> #include <map> #include <unordered_map> const double eps = 1e-8; const int M = 100010; struct fastIO { static const int BUFF_SZ = 1 << 18; char inbuf[BUFF_SZ], outbuf[BUFF_SZ]; fastIO() { setvbuf(stdin, inbuf, _IOFBF, BUFF_SZ); setvbuf(stdout, outbuf, _IOFBF, BUFF_SZ); } } IO; int m; int op, k; struct seg { std::pair<int, int> st, ed; bool type; // true : k = 1, false : k = -1 double a; } segs[M]; bool del[M]; struct Query { int x, y, d, t; double I; } query; // X : x (y, seg_idx) Y : y (x, seg_idx) std::unordered_map<int, std::map<int, int>> X, Y; void add_point(int x, int y, int u) { X[x][y] = u, Y[y][x] = u; } void del_point(int x, int y) { X[x].erase(X[x].find(y)), Y[y].erase(Y[y].find(x)); } void add_segment(int u) { if (segs[u].type) { int x = std::min(segs[u].st.first, segs[u].ed.first) + 1; int y = std::min(segs[u].st.second, segs[u].ed.second) + 1; while (x < std::max(segs[u].st.first, segs[u].ed.first)) add_point(x, y, u), ++x, ++y; } else { int x = std::min(segs[u].st.first, segs[u].ed.first) + 1; int y = std::max(segs[u].st.second, segs[u].ed.second) - 1; while (x < std::max(segs[u].st.first, segs[u].ed.first)) add_point(x, y, u), ++x, --y; } } void del_segment(int u) { if (segs[u].type) { int x = std::min(segs[u].st.first, segs[u].ed.first) + 1; int y = std::min(segs[u].st.second, segs[u].ed.second) + 1; while (x < std::max(segs[u].st.first, segs[u].ed.first)) del_point(x, y), ++x, ++y; } else { int x = std::min(segs[u].st.first, segs[u].ed.first) + 1; int y = std::max(segs[u].st.second, segs[u].ed.second) - 1; while (x < std::max(segs[u].st.first, segs[u].ed.first)) del_point(x, y), ++x, --y; } } struct info { int seg_no; int meet_time; int nxt_dir; int meet_x, meet_y; info(int no = 0, int t = 0, int d = 0, int x = 0, int y = 0) : seg_no(no), meet_time(t), nxt_dir(d), meet_x(x), meet_y(y) {} }; std::map<int, int>::iterator it; info find_nxt(int x, int y, int dir) { if (dir == 0 || dir == 2) { if ((!Y.count(y)) || Y[y].empty()) return info(); if (dir == 0) { it = Y[y].upper_bound(x); if (it == Y[y].end()) return info(); else { int seg_no = it->second, meet_x = it->first, meet_y = y; int nxt_dir = segs[seg_no].type ? 1 : 3; int meet_time = meet_x - x; return info(seg_no, meet_time, nxt_dir, meet_x, meet_y); } } else { it = Y[y].lower_bound(x); if (it == Y[y].begin()) return info(); else { --it; int seg_no = it->second, meet_x = it->first, meet_y = y; int nxt_dir = segs[seg_no].type ? 3 : 1; int meet_time = x - meet_x; return info(seg_no, meet_time, nxt_dir, meet_x, meet_y); } } } else { if ((!X.count(x)) || X[x].empty()) return info(); if (dir == 1) { it = X[x].upper_bound(y); if (it == X[x].end()) return info(); else { int seg_no = it->second, meet_y = it->first, meet_x = x; int nxt_dir = segs[seg_no].type ? 0 : 2; int meet_time = meet_y - y; return info(seg_no, meet_time, nxt_dir, meet_x, meet_y); } } else { it = X[x].lower_bound(y); if (it == X[x].begin()) return info(); else { --it; int seg_no = it->second, meet_y = it->first, meet_x = x; int nxt_dir = segs[seg_no].type ? 2 : 0; int meet_time = y - meet_y; return info(seg_no, meet_time, nxt_dir, meet_x, meet_y); } } } } struct ans { int x, y; int I; ans(int _x = 0, int _y = 0, int i = 0) : x(_x), y(_y), I(i) {} void print() const { printf("%d %d %d\n", x, y, I); } }; std::pair<int, int> striaght(int cur_x, int cur_y, int cur_dir, int cur_time) { if (cur_dir == 0) return std::make_pair(cur_x + cur_time, cur_y); else if (cur_dir == 1) return std::make_pair(cur_x, cur_y + cur_time); else if (cur_dir == 2) return std::make_pair(cur_x - cur_time, cur_y); else return std::make_pair(cur_x, cur_y - cur_time); } ans solve(const Query& q) { int cur_x = q.x, cur_y = q.y, cur_dir = q.d; double I = q.I; int remain = q.t; while (I >= (1.0 - eps) && remain > 0) { info nxt = find_nxt(cur_x, cur_y, cur_dir); if ((!nxt.seg_no) || (nxt.meet_time > remain)) { std::pair<int, int> stat = striaght(cur_x, cur_y, cur_dir, remain); return ans(stat.first, stat.second, (int)(I + eps)); } else { remain -= nxt.meet_time; I *= segs[nxt.seg_no].a; cur_x = nxt.meet_x, cur_y = nxt.meet_y, cur_dir = nxt.nxt_dir; } } if (I < (1.0 - eps)) return ans(); else return ans(cur_x, cur_y, (int)(I + eps)); } int main() { scanf("%d", &m); for (int i = 1; i <= m; ++i) { scanf("%d", &op); if (op == 1) { scanf("%d%d%d%d%lf", &segs[i].st.first, &segs[i].st.second, &segs[i].ed.first, &segs[i].ed.second, &segs[i].a); segs[i].type = (segs[i].st.first < segs[i].ed.first) == (segs[i].st.second < segs[i].ed.second); add_segment(i); } else if (op == 2) { scanf("%d", &k); del[k] = 1; del_segment(k); } else { scanf("%d%d%d%lf%d", &query.x, &query.y, &query.d, &query.I, &query.t); solve(query).print(); } } }
- 1
Information
- ID
- 31
- Time
- 2000ms
- Memory
- 512MiB
- Difficulty
- 3
- Tags
- # Submissions
- 18
- Accepted
- 2
- Uploaded By