码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1095: [ZJOI2007]Hide 捉迷藏

时间:2016-06-12 20:14:11      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:

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

 

点分治:

主要就是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\n", 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 }
点分治

 

bzoj1095: [ZJOI2007]Hide 捉迷藏

标签:

原文地址:http://www.cnblogs.com/showson/p/5578611.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!