zoukankan      html  css  js  c++  java
  • bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节。。

     

    点分治:时空复杂度$O(nlog^2n)$,常数巨大

    主要就是3个堆的初始状态

    C堆:每个节点一个,为子树中的点到它父亲的距离的堆。

    B堆:每个节点一个,存所有儿子的堆的堆顶。特别地,如果该节点关灯,那么将加入一个0;如果没有元素,堆顶应返回负数。

    A堆:全局一个,存所有B堆的最大值和最小值之和。特别地,如果B堆不足两个,返回负数。

    这样,我们一开始需要关闭所有的等,即对所有点调用一次turn_off。由于堆顶返回的是负数,删除时找不到的话直接忽略即可,如果返回的是0,则有可能误删有用的信息。

     

    代码:

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int N = 100000 + 10, logn = 17;
      6 
      7 struct RMQ {
      8     int n, f[logn + 1][N * 2], Log[N * 2];
      9     void init(int n) {
     10         Log[0] = -1;
     11         for(int i = 1; i <= n; i++) Log[i] = Log[i >> 1] + 1;
     12         this->n = n;
     13         for(int i = 1; (1 << i) < n; i++) {
     14             for(int j = 1; j <= n; j++) {
     15                 f[i][j] = min(f[i-1][j], f[i-1][j + (1 << (i-1))]);
     16             }
     17         }
     18     }
     19 
     20     int query(int l, int r) {
     21         int t = Log[r - l + 1];
     22         return min(f[t][l], f[t][r - (1 << t) + 1]);
     23     }
     24 } rmq;
     25 
     26 struct Edge {
     27     int to; Edge *next;
     28 } pool[N * 2], *pis = pool, *fir[N];
     29 
     30 void AddEdge(int u, int v) {
     31     pis->to = v, pis->next = fir[u], fir[u] = pis++;
     32 }
     33 
     34 int dfn[N], dfs_clock, *seq = rmq.f[0], dep[N], ds[N], tot;
     35 
     36 #define v p->to
     37 void dfs(int u, int fa) {
     38     dfn[u] = ++dfs_clock;
     39     seq[dfs_clock] = dep[u];
     40     for(Edge *p = fir[u]; p; p = p->next) {
     41         if(v != fa) {
     42             dep[v] = dep[u] + 1, dfs(v, u);
     43             seq[++dfs_clock] = dep[u];
     44         }
     45     }
     46     ds[tot++] = u;
     47 }
     48 #undef v
     49 
     50 int dis(int u, int v) {
     51     if(dfn[u] > dfn[v]) swap(u, v);
     52     return dep[u] + dep[v] - (rmq.query(dfn[u], dfn[v]) << 1);
     53 }
     54 const int INF = 1 << 29;
     55 
     56 struct Set {
     57     multiset<int> s;
     58     void insert(int x) {s.insert(x);}
     59     void erase(int x) {
     60         multiset<int>::iterator it = s.find(x);
     61         if(it != s.end()) s.erase(it);
     62     }
     63     int size() const {return s.size();}
     64     int top() {return s.empty() ? -INF : *--s.end();}
     65     int    query() {
     66         if(s.size() < 2) return -INF;
     67         return *--s.end() + *----s.end();
     68     }
     69 } A, B[N], C[N];
     70 
     71     void print(const Set &ss) {
     72         const multiset<int> &s = ss.s;
     73         for(multiset<int>::iterator it = s.begin(); it != s.end(); ++it) {
     74             printf("%d ", *it);
     75         }
     76         puts("");
     77     }
     78 bool centre[N];
     79 int fa[N], maxsz[N], sz[N], root;
     80 
     81 #define v p->to
     82 void dfs_size(int u, int fa) {
     83     sz[u] = 1, maxsz[u] = 0;
     84     for(Edge *p = fir[u]; p; p = p->next) {
     85         if(!centre[v] && v != fa) {
     86             dfs_size(v, u);
     87             sz[u] += sz[v];
     88             maxsz[u] = max(maxsz[u], sz[v]);
     89         }
     90     }
     91 }
     92 
     93 void dfs_root(int u, int fa, int r) {
     94     maxsz[u] = max(maxsz[u], sz[r] - sz[u]);
     95     if(maxsz[u] < maxsz[root]) root = u;
     96     for(Edge *p = fir[u]; p; p = p->next) {
     97         if(!centre[v] && v != fa) dfs_root(v, u, r);
     98     }
     99 }
    100 
    101 void divide(int u, int _fa) {
    102     dfs_size(u, 0), dfs_root(u, 0, root = u);
    103     centre[u = root] = 1, fa[u] = _fa;
    104     for(Edge *p = fir[u]; p; p = p->next) {
    105         if(!centre[v]) divide(v, u);
    106     }
    107 }
    108 #undef v
    109 
    110 void add(int u, int v, int flag) {
    111     if(u == v) {
    112         A.erase(B[u].query());
    113         if(flag) B[u].insert(0);
    114         else B[u].erase(0);
    115         A.insert(B[u].query());
    116     }
    117     int f = fa[u];
    118     if(!f) return;
    119     A.erase(B[f].query());
    120     B[f].erase(C[u].top());
    121     if(flag) C[u].insert(dis(f, v));
    122     else C[u].erase(dis(f, v));
    123     B[f].insert(C[u].top());
    124     A.insert(B[f].query());
    125     add(f, v, flag);
    126 }
    127 
    128 int col[N];
    129 
    130 int main() {
    131 #ifdef DEBUG
    132     freopen("in.txt", "r", stdin);
    133 #endif
    134 
    135     int n; scanf("%d", &n);
    136     for(int i = 1; i < n; i++) {
    137         int u, v; scanf("%d%d", &u, &v);
    138         AddEdge(u, v), AddEdge(v, u);
    139     }
    140     dfs(1, 0);
    141     rmq.init((n << 1) - 1);
    142     divide(1, 0);
    143     int cnt_off = n;
    144     for(int i = 0; i < n; i++)
    145         add(ds[i], ds[i], col[ds[i]] = 1);
    146     
    147     int m, u; scanf("%d", &m);
    148     char opt[8];
    149     while(m--) {
    150         scanf("%s", opt);
    151         if(opt[0] == 'G') {
    152             if(cnt_off == 0) puts("-1");
    153             else if(cnt_off == 1) puts("0");
    154             else printf("%d
    ", A.top());
    155         } else {
    156             scanf("%d", &u), add(u, u, col[u] ^= 1);
    157             if(col[u]) cnt_off++; else cnt_off--;
    158         }
    159     }
    160 
    161     return 0;
    162 }
    点分治

    括号序列:时间复杂度$O(nlog n)$,空间复杂度$O(n)$

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int N = 100000 + 10;
      6 
      7 int col[N];
      8 const int bracket[] = {-2, -1};
      9 
     10 struct Data {
     11     /*
     12         0 : 从区间左起的
     13         [ x ] x的数量
     14 
     15         c[] 是左右括号的数量,而d[]和s[]必须保证旁边至少有一个满足条件的点
     16     */
     17     int c[2]; // [ )...) ] 或 [ (...( ]
     18     int d[2]; // [ )...) ] - [ (...( ] 或反过来
     19     int s[2]; // [ )...) ] + [ (...( ] 或反过来 
     20     int ans;
     21 
     22     void set(int x) {
     23         for(int i = 0; i < 2; i++) {
     24             c[i] = x == bracket[i];
     25             d[i] = s[i] = x > 0 && col[x] ? 0 : -(1 << 29);
     26             // 只有在x是满足条件的点的时候才把d[]和s[]赋为0,否则为-INF
     27         }
     28     }
     29 };
     30 
     31 void maxit(int &x, int y) {
     32     if(x < y) x = y;
     33 }
     34 
     35 // 实际上需要讨论lhs.c[1] 和 rhs.c[0]的大小
     36 // 但是不合法的一定不是最优的,所以可以对两种情况直接取max
     37 Data operator + (const Data &lhs, const Data &rhs) {
     38     static Data res;
     39 
     40     // update ans
     41     res.ans = max(lhs.ans, rhs.ans);
     42     maxit(res.ans, lhs.s[1] + rhs.d[0]);
     43     maxit(res.ans, lhs.d[1] + rhs.s[0]);
     44 
     45     // update s[]
     46     res.s[0] = max(lhs.s[0], rhs.s[0] - lhs.c[1] + lhs.c[0]); // lhs.c[1] >= rhs.c[0]
     47     res.s[0] = max(res.s[0], lhs.c[0] + lhs.c[1] + rhs.d[0]); // lhs.c[1] <= rhs.c[0]
     48     res.s[1] = max(rhs.s[1], lhs.s[1] - rhs.c[0] + rhs.c[1]); // rhs.c[1] >= lhs.c[0]
     49     res.s[1] = max(res.s[1], rhs.c[0] + rhs.c[1] + lhs.d[1]); // rhs.c[1] <= rhs.c[0]
     50 
     51     // update d[]
     52     res.d[0] = max(lhs.d[0], rhs.d[0] + lhs.c[1] - lhs.c[0]);
     53     res.d[1] = max(rhs.d[1], lhs.d[1] + rhs.c[0] - rhs.c[1]);
     54 
     55     // update c[] to update next s[] and d[]
     56     res.c[0] = lhs.c[0] + max(rhs.c[0] - lhs.c[1], 0);
     57     res.c[1] = rhs.c[1] + max(lhs.c[1] - rhs.c[0], 0);
     58 
     59     return res;
     60 }
     61 
     62 struct Edge {int to; Edge *next;} pool[N * 2], *pis = pool, *fir[N];
     63 void AddEdge(int u, int v) {pis->to = v, pis->next = fir[u], fir[u] = pis++;}
     64 
     65 int dfs_seq[N * 3], dfs_clock;
     66 
     67 void dfs(int u, int fa) {
     68     col[u] = 1;
     69     dfs_seq[++dfs_clock] = bracket[1];
     70     dfs_seq[++dfs_clock] = u;
     71     for(Edge *p = fir[u]; p; p = p->next) {
     72         int v = p->to;
     73         if(v != fa) dfs(v, u);
     74     }
     75     dfs_seq[++dfs_clock] = bracket[0];
     76 }
     77 
     78 int pos[N];
     79 
     80 struct SegmentTree {
     81     Data da[N * 12];
     82     void build(int s, int l, int r, int a[]) {
     83         if(l == r) {
     84             if(a[l] > 0) pos[a[l]] = s;
     85             return da[s].set(a[l]);
     86         }
     87         int mid = (l + r) >> 1;
     88         build(s << 1, l, mid, a), build(s << 1 | 1, mid + 1, r, a);
     89         da[s] = da[s << 1] + da[s << 1 | 1];
     90     }
     91 
     92     void modify(int x) {
     93         int s = pos[x]; da[s].set(x);
     94         while(s >>= 1) da[s] = da[s << 1] + da[s << 1 | 1];
     95     }
     96 } seg;
     97 
     98 int main() {
     99 #ifdef DEBUG
    100     freopen("in.txt", "r", stdin);
    101 #endif
    102 
    103     int n; scanf("%d", &n);
    104     for(int i = 1; i < n; i++) {
    105         int u, v; scanf("%d%d", &u, &v);
    106         AddEdge(u, v), AddEdge(v, u);
    107     }
    108     dfs(1, 0);
    109     seg.build(1, 1, n * 3, dfs_seq);
    110 
    111     int m; scanf("%d", &m);
    112     char opt[8]; int ans, x, cnt = n;
    113     while(m--) {
    114         scanf("%s", opt);
    115         if(opt[0] == 'G') {
    116             if(cnt >= 2) ans = seg.da[1].ans;
    117             else if(cnt == 1) ans = 0;
    118             else ans = -1;
    119             printf("%d
    ", ans);
    120         } else {
    121             scanf("%d", &x);
    122             if(col[x] ^= 1) cnt++; else cnt--;
    123             seg.modify(x);
    124         }
    125     }
    126 
    127     return 0;
    128 }
    线段树
     
    链分治:时间复杂度$O(nlog^2n)$,空间复杂度$O(n)$ 比点分治快多啦
    notice:合并两个线段树节点的时候如果使用=赋值可能丢失儿子信息。
      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int N = 100000 + 10, INF = 1 << 29;
      6 
      7 struct Set {
      8     multiset<int> s;
      9     void erase(int x) {assert(s.find(x) != s.end()), s.erase(s.find(x));}
     10     void insert(int x) {s.insert(x);}
     11     int top() const {return s.empty() ? -INF : *--s.end();}
     12     int query() const {
     13         if(s.size() < 2) return -INF;
     14         return *--s.end() + *----s.end();
     15     }
     16 } heap[N], st;
     17 
     18 void print(const Set &ss) {
     19     const multiset<int> &s = ss.s;
     20     for(multiset<int>::iterator it = s.begin(); it != s.end(); ++it) {
     21         printf("%d ", *it);
     22     }
     23     puts("");
     24 }
     25 
     26 struct Edge {
     27     int to, w;
     28     Edge *next;
     29 } pool_edges[N * 2], *fir[N], *pe = pool_edges;
     30 
     31 void AddEdge(int u, int v, int w) {
     32     pe->to = v, pe->w = w, pe->next = fir[u], fir[u] = pe++;
     33 }
     34 
     35 int sz[N], top[N], dis[N], son[N], fa[N], dfs_clock, seq[N], dfn[N], end[N], col[N];
     36 
     37 #define mid ((l + r) >> 1)
     38 struct Node {
     39     int L, R, ans;
     40     Node *ch[2];
     41 
     42     void set(int u) {
     43         ans = heap[u].query();
     44         L = R = heap[u].top();
     45     }
     46 
     47     void modify(int l, int r, int p);
     48 
     49 } pool_nodes[N * 3], *pn = pool_nodes, *rt[N];
     50 
     51 void print(Node *o, int l, int r) {
     52     printf("[%d, %d] : L = %d, R = %d, ans = %d
    ", l, r, o->L, o->R, o->ans);
     53     if(l != r) print(o->ch[0], l, mid), print(o->ch[1], mid + 1, r);
     54 }
     55 void merge(Node &res, const Node &lhs, const Node &rhs, int l, int r) {
     56     res.ans = max(lhs.ans, rhs.ans);
     57     res.ans = max(res.ans, lhs.R + dis[seq[mid + 1]] - dis[seq[mid]] + rhs.L);
     58 
     59     res.L = max(lhs.L, dis[seq[mid + 1]] - dis[seq[l]] + rhs.L);
     60     res.R = max(rhs.R, dis[seq[r]] - dis[seq[mid]] + lhs.R);
     61 }
     62 
     63 void Node::modify(int l, int r, int p) {
     64     if(l == r) return set(seq[p]);
     65     if(p <= mid) ch[0]->modify(l, mid, p);
     66     else ch[1]->modify(mid + 1, r, p);
     67     merge(*this, *ch[0], *ch[1], l, r);
     68 }
     69 
     70 Node *build(int l, int r) {
     71     Node *o = pn++;
     72     if(l == r) o->set(seq[l]);
     73     else {
     74         o->ch[0] = build(l, mid);
     75         o->ch[1] = build(mid + 1, r);
     76         merge(*o, *o->ch[0], *o->ch[1], l, r);
     77     }
     78     return o;
     79 }
     80 #undef mid
     81 
     82 #define v it->to
     83 void dfs_size(int u) {
     84     sz[u] = 1, col[u] = 1;
     85     for(Edge *it = fir[u]; it; it = it->next) {
     86         if(v != fa[u]) {
     87             dis[v] = dis[u] + it->w;
     88             fa[v] = u;
     89             dfs_size(v);
     90             sz[u] += sz[v];
     91             if(sz[v] > sz[son[u]]) son[u] = v;
     92         }
     93     }
     94 }
     95 
     96 void dfs_build(int u, int pre) {
     97     seq[dfn[u] = ++dfs_clock] = u;
     98     top[u] = pre;
     99     end[pre] = max(end[pre], dfn[u]);
    100     if(son[u]) dfs_build(son[u], pre);
    101     for(Edge *it = fir[u]; it; it = it->next) {
    102         if(v != fa[u] && v != son[u]) {
    103             dfs_build(v, v);
    104             heap[u].insert(rt[v]->L + dis[v] - dis[u]);
    105         }
    106     }
    107 
    108     heap[u].insert(0);
    109     if(top[u] == u) {
    110         rt[u] = build(dfn[u], end[u]);
    111         st.insert(rt[u]->ans);
    112     }
    113 }
    114 #undef v
    115 
    116 void modify(int u) { 
    117     static int anc[20], tot;
    118     tot = 0;
    119     for(int t = u; t; t = fa[top[t]]) anc[tot++] = t;
    120 
    121     for(int i = tot-1; i >= 0; i--) {
    122         st.erase(rt[top[anc[i]]]->ans);
    123         if(i) heap[anc[i]].erase(rt[top[anc[i-1]]]->L + dis[top[anc[i-1]]] - dis[anc[i]]);
    124     }
    125     if(col[u]) heap[u].insert(0);
    126     else heap[u].erase(0);
    127 
    128     for(int i = 0; i < tot; i++) {
    129         int x = anc[i], t = top[x];
    130         rt[t]->modify(dfn[t], end[t], dfn[x]);
    131         st.insert(rt[t]->ans);
    132         if(i+1 < tot) heap[anc[i+1]].insert(rt[t]->L + dis[t] - dis[anc[i+1]]);
    133     }
    134 }
    135 
    136 int main() {
    137 #ifdef DEBUG
    138     freopen("in.txt", "r", stdin);
    139 #endif
    140     int n; scanf("%d", &n);
    141     for(int i = 1; i < n; i++) {
    142         int u, v; scanf("%d%d", &u, &v);
    143         AddEdge(u, v, 1), AddEdge(v, u, 1);
    144     }
    145     dfs_size(1);
    146     dfs_build(1, 1);
    147 
    148     int m; scanf("%d", &m);
    149     char opt[8]; int u, tot = n;
    150     while(m--) {
    151         scanf("%s", opt);
    152         if(opt[0] == 'G') {
    153             int ans;
    154             if(tot == 0) ans = -1;
    155             else if(tot == 1) ans = 0;
    156             else ans = st.top();
    157             printf("%d
    ", ans);
    158         } else {
    159             scanf("%d", &u);
    160             if(!(col[u] ^= 1)) tot--; else tot++;
    161             modify(u);
    162             
    163         }
    164     }
    165 }
    链分治
  • 相关阅读:
    黑客防线
    基于onvif的码流转换专利
    8168开发之---1g内存换成512M的内存映射配置
    图像处理之基础---内积、点积
    3s 简介
    嵌入式开发之工具---比开发手册更重要的一个命令 man page
    图像处理之基础---频域分析
    lbp纹理特征
    28.Docker介绍与目录
    09.客户端集成IdentityServer
  • 原文地址:https://www.cnblogs.com/showson/p/5578611.html
Copyright © 2011-2022 走看看