Old Christmas Lights II

Old Christmas Lights II

简要题意:求树上路径点权的最小差值。

题解:树上莫队转移+数据结构维护最小差值。

一开始用multiset,结果疯狂TLE。改成分块维护就过了。貌似块分小点跑的更快?

还可以用平衡树或者线段树维护,不过咱没有写。

  1 #include<cassert>
  2 #include<set>
  3 #include<map>
  4 #include<cmath>
  5 #include<cstdio>
  6 #include<iostream>
  7 #include<algorithm>
  8 using namespace std;
  9 inline char nc() {
 10     static char b[1<<16],*s=b,*t=b;
 11     return s==t&&(t=(s=b)+fread(b,1,1<<16,stdin),s==t)?-1:*s++;
 12 }
 13 inline void read(int &x) {
 14     char b = nc(); x = 0;
 15     for (; !isdigit(b); b = nc());
 16     for (; isdigit(b); b = nc()) x = x * 10 + b - '0';
 17 }
 18 const int N = 50005;
 19 struct Edge {int v,n;} E[N*2];
 20 int n, m, head[N], ecnt, val[N], ans[N];
 21 int sz[N], son[N], fa[N], dep[N], top[N];
 22 int I[N], O[N], s[N*2], D, S, bl[N*2];
 23 bool oc[N];
 24 inline void ae(int u, int v) {
 25     E[++ecnt] = (Edge){v, head[u]}; head[u] = ecnt;
 26     E[++ecnt] = (Edge){u, head[v]}; head[v] = ecnt;
 27 }
 28 inline int ABS(int x) {return x > 0 ? x : -x;}
 29 void dfs1(int u, int f) {
 30     sz[u] = 1; fa[u] = f; dep[u] = dep[f] + 1;
 31     for (int v, i = head[u]; i; i = E[i].n) if ((v = E[i].v) != f) {
 32         dfs1(v, u); sz[u] += sz[v]; if (sz[son[u]] < sz[v]) son[u] = v;
 33     }
 34 }
 35 void dfs2(int u, int tp) {
 36     I[u] = ++D; s[D] = u;
 37     top[u] = tp; if (son[u]) dfs2(son[u], tp);
 38     for (int v, i = head[u]; i; i = E[i].n) 
 39         if (v = E[i].v, v != fa[u] && v != son[u]) dfs2(v, v);
 40     O[u] = ++D; s[D] = u;
 41 }
 42 int findLca(int a, int b) {
 43     for (; top[a] != top[b]; a = fa[top[a]])
 44         if (dep[top[a]] < dep[top[b]]) swap(a, b);
 45     return dep[a] < dep[b] ? a : b;
 46 }
 47 struct QA {
 48     int l, r, e, id;
 49     inline void init(int u, int v, int i) {
 50         id = i; if (I[u] > I[v]) swap(u, v);
 51         e = findLca(u, v);
 52         if (u == e) e = 0, l = I[u], r = I[v];
 53         else l = O[u], r = I[v];
 54         if (l > r) swap(l, r);
 55     }
 56     inline bool operator<(const QA &q) const {
 57         if (bl[l] != bl[q.l]) return bl[l] < bl[q.l];
 58         return r < q.r;
 59     }
 60 } q[N];
 61 namespace MN {
 62 #define fir first
 63 #define sec second
 64     typedef long long ll;
 65     const ll inf = 1e10;
 66     pair < int , int > v[N];
 67     int H, r[N], cnt[N], S, bl[N], B;
 68     ll mx[5000], mn[5000], w[5000];
 69     template < class T1, class T2 > inline void gmax(T1 &x, T2 y) {if (x < y) x = y;}
 70     template < class T1, class T2 > inline void gmin(T1 &x, T2 y) {if (x > y) x = y;}
 71     inline void init() {
 72         for (int i = 1; i <= n; ++i) v[i].fir = val[i], v[i].sec = i;
 73         sort(v + 1, v + 1 + n); H = 0;
 74         for (int i = 1; i <= n; ++i) {
 75             if (v[i].fir != v[i-1].fir) r[++H] = v[i].fir;
 76             val[v[i].sec] = H;
 77         } S = max(1.0, sqrt(H / 5)); B = (H - 1) / S + 1;
 78         for (int i = 1; i <= H; ++i) bl[i] = (i - 1) / S + 1;
 79         for (int i = 1; i <= B; ++i) mx[i] = -inf, mn[i] = inf, w[i] = inf;
 80     }
 81     inline void addv(int x) {
 82         if (++cnt[x] == 1) {
 83             for (int i = x + 1; bl[i] == bl[x]; ++i) 
 84                 if (cnt[i]) {gmin(w[bl[x]], (r[i] - r[x])); break;}
 85             for (int i = x - 1; bl[i] == bl[x]; --i)
 86                 if (cnt[i]) {gmin(w[bl[x]], (r[x] - r[i])); break;}
 87             gmax(mx[bl[x]], r[x]); gmin(mn[bl[x]], r[x]);
 88             assert(w[bl[x]] >= 0);
 89         } else if (cnt[x] > 1) w[bl[x]] = 0;
 90     }
 91     inline void delv(int x) {
 92         if (--cnt[x] < 2) {
 93             ll p = -inf; int b = bl[x]; mx[b] = -inf, mn[b] = w[b] = inf;
 94             for (int i = (b - 1) * S + 1; i < b * S + 1 && i <= H; ++i) if (cnt[i]) {
 95                 gmax(mx[b], r[i]), gmin(mn[b], r[i]);
 96                 gmin(w[b], ll(r[i]) - p); p = r[i];
 97                 assert(w[b] >= 0);
 98                 if (cnt[i] > 1) w[b] = 0;
 99             }
100         }    
101     }
102     inline ll query() {
103         ll res = w[1], p = mx[1], t;
104         for (int i = 2; i <= B; ++i) {
105             gmin(res, w[i]); 
106             assert(res >= 0);
107             t = mn[i] - p;
108             gmin(res, t); // add uint here after debug
109             assert(res >= 0);
110             gmax(p, mx[i]);
111         } return res;
112     }
113 };
114 using MN::addv;
115 using MN::delv;
116 using MN::query;
117 inline void updn(int u) {
118     if (oc[u] ^= 1) addv(val[u]); else delv(val[u]);
119 }
120 void solve() {
121     sort(q, q + m);
122     for (int l = 1, r = 0, i = 0; i < m; ++i) {
123         //printf("%d %d %d %d\n", q[i].l, q[i].r, q[i].e, q[i].id);
124         while (r < q[i].r) updn(s[++r]);
125         while (r > q[i].r) updn(s[r--]);
126         while (l < q[i].l) updn(s[l++]);
127         while (l > q[i].l) updn(s[--l]);
128         if (q[i].e) updn(q[i].e);
129         ans[q[i].id] = query();
130         if (q[i].e) updn(q[i].e);
131     }
132     for (int i = 0; i < m; ++i) printf("%d\n", ans[i]);
133 }
134 int main() {
135     read(n); read(m); S = sqrt(n * 2) + 1;
136     for (int i = 1; i <= n * 2; ++i) bl[i] = (i - 1) / S + 1;
137     for (int i = 1; i <= n; ++i) read(val[i]);
138     MN::init();
139     for (int u, v, i = 1; i < n; ++i) read(u), read(v), ae(u, v);
140     dfs1(1, 1); dfs2(1, 1);
141     for (int u, v, i = 0; i < m; ++i) read(u), read(v), q[i].init(u, v, i);
142     //for (int i = 1; i <= n * 2; ++i) printf("%d ", s[i]); puts("");
143     solve();
144     return 0;
145 }

 

 

posted @ 2018-01-04 22:02  p0ny  阅读(98)  评论(0编辑  收藏  举报