标签:
我们把边按权值从大到小依次加入图中
如果加到边权$V$,则当前的最小生成森林中边权$v\in[V, V‘]$(其中$V‘$是任意值)形成的森林的边权和就是对于询问$[V, V‘]$的答案
由于点数不多,所以可以每次暴力$dfs$找环上最大边以及暴力删除。。。
又由于是强制在线,于是用可持久化线段树维护不同权值的出现次数即可
1 /************************************************************** 2 Problem: 4046 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:8788 ms 7 Memory:46132 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 using namespace std; 15 const int N = 1e3 + 5; 16 const int M = 1e5 + 5; 17 const int maxV = 1e6 + 5; 18 19 int read(); 20 21 struct Edge { 22 int x, y, v; 23 24 inline bool operator < (const Edge &e) const { 25 return v > e.v; 26 } 27 28 inline void get() { 29 x = read(), y = read(), v = read(); 30 } 31 } E[M]; 32 33 struct edge { 34 int next, to, v; 35 edge() {} 36 edge(int _n, int _t, int _v) : next(_n), to(_t), v(_v) {} 37 } e[M << 1]; 38 39 struct chair_tree { 40 chair_tree *ls, *rs; 41 int sum; 42 43 #define Cnt 3500000 44 inline void* operator new(size_t, chair_tree *_c = NULL, int f = 0) { 45 static chair_tree mempool[Cnt], *c; 46 if (f) c = mempool; 47 if (_c == NULL) 48 c -> ls = c -> rs = NULL, c -> sum = 0; 49 else *c = *_c; 50 return c++; 51 } 52 #undef Cnt 53 54 #define mid (l + r >> 1) 55 void modify(int l, int r, int pos, int d) { 56 sum += d; 57 if (l == r) return; 58 if (pos <= mid) { 59 ls = new(ls)chair_tree; 60 ls -> modify(l, mid, pos, d); 61 } else { 62 rs = new(rs)chair_tree; 63 rs -> modify(mid + 1, r, pos, d); 64 } 65 } 66 67 int query(int l, int r, int L, int R) { 68 if (L <= l && r <= R) return sum; 69 int res = 0; 70 if (ls && L <= mid) res += ls -> query(l, mid, L, R); 71 if (rs && mid < R) res += rs -> query(mid + 1, r, L, R); 72 return res; 73 } 74 #undef mid 75 } *root[M]; 76 77 int n, m, ans; 78 int first[N], tot; 79 int fa[N]; 80 int tmp[M], len; 81 82 inline void Add_Edges(int x, int y, int v) { 83 e[++tot] = edge(first[x], y, v), first[x] = tot; 84 e[++tot] = edge(first[y], x, v), first[y] = tot; 85 } 86 87 #define y e[x].to 88 inline void Delete_Edge(int p, int q) { 89 int x; 90 if (e[first[p]].to == q) { 91 first[p] = e[first[p]].next; 92 return; 93 } 94 for (x = first[p]; x; x = e[x].next) 95 if (e[e[x].next].to == q) { 96 e[x].next = e[e[x].next].next; 97 return; 98 } 99 } 100 101 inline void Delete_Edges(int p, int q) { 102 Delete_Edge(p, q); 103 Delete_Edge(q, p); 104 } 105 106 int find_max(int p, int fa, int tar) { 107 int x, tmp; 108 for (x = first[p]; x; x = e[x].next) 109 if (y != fa) { 110 if (y == tar) return x; 111 tmp = find_max(y, p, tar); 112 if (tmp != -1) { 113 if (e[tmp].v > e[x].v) return tmp; 114 return x; 115 } 116 } 117 return -1; 118 } 119 #undef y 120 121 int find(int x) { 122 return fa[x] == x ? x : fa[x] = find(fa[x]); 123 } 124 125 inline int get(int x) { 126 return lower_bound(tmp + 1, tmp + len + 1, x) - tmp; 127 } 128 129 int main() { 130 int T, now, i, x, y, Q; 131 for (T = read(); T; --T) { 132 n = read(), m = read(), ans = 0; 133 for (i = 1; i <= n; ++i) fa[i] = i; 134 for (i = 1; i <= m; ++i) { 135 E[i].get(); 136 tmp[i] = E[i].v; 137 } 138 sort(E + 1, E + m + 1); 139 sort(tmp + 1, tmp + m + 1), len = unique(tmp + 1, tmp + m + 1) - tmp - 1; 140 memset(first, 0, sizeof(first)), tot = 1; 141 142 root[len + 1] = new(NULL, 1)chair_tree; 143 for (now = len, i = 1; now; --now) { 144 root[now] = new(root[now + 1])chair_tree; 145 for (; E[i].v == tmp[now] && i <= m; ++i) { 146 x = find(E[i].x), y = find(E[i].y); 147 if (x != y) fa[x] = y; 148 else { 149 x = find_max(E[i].x, 0, E[i].y); 150 Delete_Edges(e[x].to, e[x ^ 1].to); 151 root[now] -> modify(1, len, get(e[x].v), -e[x].v); 152 } 153 Add_Edges(E[i].x, E[i].y, E[i].v); 154 root[now] -> modify(1, len, get(E[i].v), E[i].v); 155 } 156 } 157 for (Q = read(); Q; --Q) { 158 x = read(), y = read(); 159 x = upper_bound(tmp + 1, tmp + len + 1, x - ans - 1) - tmp; 160 y = upper_bound(tmp + 1, tmp + len + 1, y - ans) - tmp - 1; 161 if (x > y) printf("%d\n", ans = 0); 162 else printf("%d\n", ans = root[x] -> query(1, len, x, y)); 163 } 164 } 165 return 0; 166 } 167 168 inline int read() { 169 static int x; 170 static char ch; 171 x = 0, ch = getchar(); 172 while (ch < ‘0‘ || ‘9‘ < ch) 173 ch = getchar(); 174 while (‘0‘ <= ch && ch <= ‘9‘) { 175 x = x * 10 + ch - ‘0‘; 176 ch = getchar(); 177 } 178 return x; 179 }
BZOJ4046 [Cerc2014] Pork barre
标签:
原文地址:http://www.cnblogs.com/rausen/p/4528842.html