• UOJ 191


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

    1. 在末尾加入一个新向量
    2. 删除末尾的向量
    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 }
  • 相关阅读:
    Linux命令-查看进程
    Linux命令-查看内存
    Linux命令---vim
    oracle分页查询按日期排序失败问题
    oracle使用between and边界问题
    给大家介绍一个自我感觉好用的网站
    想学习一下微服务
    oracle获取年、月、日
    mybatis返回map结果集
    修改表中列
  • 原文地址:https://www.cnblogs.com/sjkmost/p/10770946.html
Copyright © 2020-2023  润新知