有一个初始为空的向量序列,要求你支持3种操作:
- 在末尾加入一个新向量
- 删除末尾的向量
- 询问区间中向量与给定向量的叉积最大值
令$m$为操作数,$n$为插入操作数。
$$mle 5 imes 10^5,n le 3 imes 10^5$$
多组数据(不超过3组),3秒,64M。
先将叉积转成点积。
考虑操作实际上把这个序列变成了一棵树,而询问相当于询问树上的一条没有拐点的链。
一个显然的结论是答案一定在凸壳上,为了处理询问,可以直接链剖,但是空间会被卡。
为了把空间复杂度降到$O(n)$,我们选择点分,在每一个分治出的连通块里,设深度最小的节点为$R$,重心为$G$,我们每次处理$R$到$G$的路径上的点对$R$子树内的询问的贡献。
具体的说,每个询问相当于询问当前路径的一个前缀上的答案,我们发现询问在按极角序排序后,在凸壳上的答案是单调的,可以扫一遍得到贡献。
那么直接CDQ分治就行了。
时间复杂度$O(mlog^2 n)$。
1 #include <bits/stdc++.h> 2 3 #define IL __inline__ __attribute__((always_inline)) 4 5 #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i) 6 #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i) 7 #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i) 8 #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i) 9 10 typedef long long LL; 11 12 template <class T> 13 IL bool chkmax(T &a, const T &b) { 14 return a < b ? ((a = b), 1) : 0; 15 } 16 17 template <class T> 18 IL bool chkmin(T &a, const T &b) { 19 return a > b ? ((a = b), 1) : 0; 20 } 21 22 template <class T> 23 IL T mymax(const T &a, const T &b) { 24 return a > b ? a : b; 25 } 26 27 template <class T> 28 IL T mymin(const T &a, const T &b) { 29 return a < b ? a : b; 30 } 31 32 template <class T> 33 IL T myabs(const T &a) { 34 return a > 0 ? a : -a; 35 } 36 37 const int INF = 0X3F3F3F3F; 38 const double EPS = 1E-10, PI = acos(-1.0); 39 40 #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 41 #define OK DEBUG("Passing [%s] in LINE %d... ", __FUNCTION__, __LINE__) 42 43 const int MAXN = 300000 + 5, MAXM = 500000 + 5, MOD = 998244353; 44 45 struct Input { 46 char buf[1 << 22], *st, *ed; 47 48 Input() { 49 #ifndef ONLINE_JUDGE 50 freopen("unknown.in", "r", stdin); 51 #endif 52 } 53 54 char get() { 55 if (st == ed) { 56 ed = buf + fread(st = buf, 1, 1 << 22, stdin); 57 } 58 return *st ++; 59 } 60 61 friend Input &operator>>(Input &io, int &x) { 62 x = 0; 63 static char ch; 64 int f = 1; 65 while (!isdigit(ch = io.get())) { 66 if (ch == '-') { 67 f = -1; 68 } 69 } 70 do { 71 x = x * 10 + ch - '0'; 72 } while (isdigit(ch = io.get())); 73 x *= f; 74 return io; 75 } 76 } cin; 77 78 struct Point { 79 int x, y; 80 81 Point() {} 82 Point(int _x, int _y) : x(_x), y(_y) {} 83 }; 84 85 typedef Point Vector; 86 87 IL Vector operator+(const Vector &a, const Vector &b) { 88 return Vector(a.x + b.x, a.y + b.y); 89 } 90 91 IL Vector operator-(const Vector &a, const Vector &b) { 92 return Vector(a.x - b.x, a.y - b.y); 93 } 94 95 IL bool operator==(const Vector &a, const Vector &b) { 96 return a.x == b.x && a.y == b.y; 97 } 98 99 IL bool operator!=(const Vector &a, const Vector &b) { 100 return !(a == b); 101 } 102 103 IL bool operator<(const Vector &a, const Vector &b) { 104 return a.x == b.x ? a.y < b.y : a.x < b.x; 105 } 106 107 IL bool operator>(const Vector &a, const Vector &b) { 108 return a.x == b.x ? a.y > b.y : a.x > b.x; 109 } 110 111 IL LL dot(const Vector &a, const Vector &b) { 112 return (LL)a.x * b.x + (LL)a.y * b.y; 113 } 114 115 IL LL cross(const Vector &a, const Vector &b) { 116 return (LL)a.x * b.y - (LL)a.y * b.x; 117 } 118 119 LL answer[MAXM]; 120 int num; 121 122 struct Command { 123 int opt, l, r, cnt; 124 Point pt; 125 } com[MAXM]; 126 127 IL bool comp(int a, int b) { 128 return cross(com[a].pt, com[b].pt) < 0; 129 } 130 131 struct Tree { 132 int hed[MAXN], nxt[MAXN * 2], to[MAXN * 2], fa[MAXN], dep[MAXN], cnt; 133 Vector pt[MAXN]; 134 bool vis[MAXN]; 135 std::vector<int> queries[MAXN]; 136 137 void init() { 138 memset(hed, 0, sizeof hed); 139 memset(nxt, 0, sizeof nxt); 140 memset(to, -1, sizeof to); 141 memset(fa, -1, sizeof fa); 142 memset(vis, 0, sizeof vis); 143 cnt = 0; 144 } 145 146 void addEdge(int u, int v) { 147 ++ cnt; 148 to[cnt] = v; 149 nxt[cnt] = hed[u]; 150 hed[u] = cnt; 151 } 152 153 std::vector<Point> solve(int l, int r, std::vector<int> &vp, int ql, int qr, std::vector<int> &vq) { 154 if (l + 1 >= r) { 155 FOR(i, ql, qr) { 156 chkmax(answer[vq[i]], dot(pt[vp[l]], com[vq[i]].pt)); 157 } 158 std::sort(vq.begin() + ql, vq.begin() + qr, comp); 159 return std::vector<Point>(1, pt[vp[l]]); 160 } 161 static int wxh[MAXM]; 162 int mid = (l + r) >> 1, f = ql, s = qr; 163 FOR(i, ql, qr) { 164 wxh[com[vq[i]].l > dep[vp[mid]] ? f ++ : -- s] = vq[i]; 165 } 166 std::copy(wxh + ql, wxh + qr, vq.begin() + ql); 167 std::vector<Point> conv_l = solve(l, mid, vp, ql, f, vq), conv_r = solve(mid, r, vp, s, qr, vq); 168 static Point flx[MAXN]; 169 std::copy(conv_l.begin(), conv_l.end(), flx + 1); 170 int size = conv_l.size(); 171 LL result = 0; 172 for (int i = f, cur = 1; i < qr; ++ i) { 173 result = cur > 1 ? dot(flx[cur - 1], com[vq[i]].pt) : -(LL)INF * INF; 174 while (cur <= size && chkmax(result, dot(flx[cur], com[vq[i]].pt))) { 175 ++ cur; 176 } 177 chkmax(answer[vq[i]], result); 178 } 179 std::vector<Point> conv(conv_l.size() + conv_r.size()); 180 std::merge(conv_l.begin(), conv_l.end(), conv_r.begin(), conv_r.end(), conv.begin()); 181 static Point stack[MAXN]; 182 int top = 0; 183 for (auto &x : conv) { 184 while (top > 1 && cross(x - stack[top - 1], stack[top] - stack[top - 1]) <= 0) { 185 -- top; 186 } 187 stack[++ top] = x; 188 } 189 std::inplace_merge(vq.begin() + ql, vq.begin() + f, vq.begin() + qr, comp); 190 return std::vector<Point>(stack + 1, stack + top + 1); 191 } 192 193 void DFS5(int u, int p, int &total) { 194 ++ total; 195 for (int e = hed[u]; e; e = nxt[e]) { 196 int v = to[e]; 197 if (!vis[v] && v != p) { 198 DFS5(v, u, total); 199 } 200 } 201 } 202 203 void DFS4(int u, int root, std::vector<int> &vec, int p) { 204 for (auto &x : queries[u]) { 205 if (com[x].l <= dep[root]) { 206 vec.push_back(x); 207 } 208 } 209 for (int e = hed[u]; e; e = nxt[e]) { 210 int v = to[e]; 211 if (!vis[v] && v != p) { 212 DFS4(v, root, vec, u); 213 } 214 } 215 } 216 217 void DFS3(int u, int aim, std::vector<int> &vec, int p) { 218 static int stack[MAXN], top; 219 stack[++ top] = u; 220 if (u == aim) { 221 vec = std::vector<int>(stack + 1, stack + top + 1); 222 } 223 for (int e = hed[u]; e; e = nxt[e]) { 224 int v = to[e]; 225 if (!vis[v] && v != p) { 226 DFS3(v, aim, vec, u); 227 } 228 } 229 -- top; 230 } 231 232 void DFS2(int u, int &cur, int &d, int total, int p) { 233 static int size[MAXN], max[MAXN]; 234 max[num + 1] = INF; 235 size[u] = 1; 236 max[u] = 0; 237 for (int e = hed[u]; e; e = nxt[e]) { 238 int v = to[e]; 239 if (!vis[v] && v != p) { 240 DFS2(v, cur, d, total, u); 241 size[u] += size[v]; 242 chkmax(max[u], size[v]); 243 } 244 } 245 if (~p) { 246 chkmax(max[u], total - size[u]); 247 } 248 if (max[u] < max[cur]) { 249 cur = u; 250 } 251 if (dep[u] < dep[d]) { 252 d = u; 253 } 254 } 255 256 void DFS1(int u, int total) { 257 int root = num + 1; 258 DFS2(u, root, u, total, -1); 259 static std::vector<int> cur; 260 cur.clear(); 261 DFS3(root, u, cur, -1); 262 for (auto &x : cur) { 263 vis[x] = 1; 264 } 265 static std::vector<int> qs; 266 qs.clear(); 267 DFS4(root, root, qs, -1); 268 for (auto &x : cur) { 269 vis[x] = 0; 270 } 271 vis[root] = 1; 272 if (!cur.back()) { 273 cur.pop_back(); 274 } 275 std::sort(qs.begin(), qs.end(), [&](int a, int b) { 276 return com[a].l > com[b].l; 277 }); 278 solve(0, cur.size(), cur, 0, qs.size(), qs); 279 for (int e = hed[root]; e; e = nxt[e]) { 280 int v = to[e]; 281 if (!vis[v]) { 282 int size = 0; 283 DFS5(v, -1, size); 284 DFS1(v, size); 285 } 286 } 287 } 288 } T; 289 290 int main() { 291 int _; 292 cin >> _; 293 while (1) { 294 int m; 295 cin >> m; 296 if (!m) { 297 break; 298 } 299 num = 0; 300 For(i, 1, m) { 301 answer[i] = -(LL)INF * INF; 302 } 303 T.init(); 304 static int stack[MAXN], top; 305 top = 0; 306 int cur = 0; 307 For(i, 1, m) { 308 cin >> com[i].opt; 309 if (com[i].opt == 1) { 310 cin >> com[i].pt.x >> com[i].pt.y; 311 T.fa[stack[++ top] = com[i].cnt = ++ num] = cur; 312 T.dep[com[i].cnt] = top; 313 T.pt[com[i].cnt] = com[i].pt; 314 T.addEdge(cur, com[i].cnt); 315 T.addEdge(com[i].cnt, cur); 316 cur = com[i].cnt; 317 } else if (com[i].opt == 2) { 318 com[i].cnt = cur = T.fa[cur]; 319 -- top; 320 } else { 321 cin >> com[i].l >> com[i].r >> com[i].pt.y >> com[i].pt.x; 322 com[i].pt.x = -com[i].pt.x; 323 T.queries[stack[com[i].r]].push_back(i); 324 } 325 } 326 T.DFS1(0, num + 1); 327 int result = 0; 328 For(i, 1, m) { 329 if (com[i].opt == 3) { 330 result ^= (answer[i] % MOD + MOD) % MOD; 331 } 332 } 333 For(i, 1, num) { 334 T.queries[i].clear(); 335 } 336 printf("%d ", result); 337 } 338 return 0; 339 }