UOJ 191

有一个初始为空的向量序列,要求你支持3种操作:

  1. 在末尾加入一个新向量
  2. 删除末尾的向量
  3. 询问区间中向量与给定向量的叉积最大值

令$m$为操作数,$n$为插入操作数。

$$m\le 5\times 10^5,n \le 3\times 10^5$$

多组数据(不超过3组),3秒,64M。

先将叉积转成点积。

考虑操作实际上把这个序列变成了一棵树,而询问相当于询问树上的一条没有拐点的链。

一个显然的结论是答案一定在凸壳上,为了处理询问,可以直接链剖,但是空间会被卡。

为了把空间复杂度降到$O(n)$,我们选择点分,在每一个分治出的连通块里,设深度最小的节点为$R$,重心为$G$,我们每次处理$R$到$G$的路径上的点对$R$子树内的询问的贡献。

具体的说,每个询问相当于询问当前路径的一个前缀上的答案,我们发现询问在按极角序排序后,在凸壳上的答案是单调的,可以扫一遍得到贡献。

那么直接CDQ分治就行了。

时间复杂度$O(m\log^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...\n", __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\n", result);
337   }
338   return 0;
339 }

 

posted @ 2019-04-25 21:01  sjkmost  阅读(318)  评论(0编辑  收藏  举报