http://acm.hdu.edu.cn/showproblem.php?pid=6039
Gear Up
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Problem Description
1. They share a common edge (i.e. they have equal linear velocity).
2. They share a common shaft (i.e. they have equal angular velocity).
It is guaranteed that no pair of gears meets both of the above conditions.
A series of continuous adjacent gears constitutes a gear path. There is at most one gear path between each two gears.
Now constroy assigns an angular velocity to one of these gears and then asks you to determine the largest angular velocity among them.
sd0061 thinks this problem is too easy, so he replaces some gears and then asks you the question again.
Input
For each test case:
The first line contains three integers $n, m, q$, the number of gears, the number of adjacent pairs and the number of operations. $(0 \leq m < n \leq 10^5, 0 \leq q \leq 10^5)$
The second line contains $n$ integers, of which the $i$-th integer represents $r_i$, the radius of the $i$-th gear. $(r_i \in \{2^\lambda \mid 0 \leq \lambda \leq 30\})$
Each of the next $m$ lines contains three integers $a, x, y$, the $x$-th gear and the $y$-th gear are adjacent in the $a$-th condition. $(a \in \{1, 2\}, 1 \leq x, y \leq n, x \neq y)$
Each of the next $q$ line contains three integers $a, x, y$, an operation ruled in the following: $(a \in \{1, 2\}, 1 \leq x \leq n, y \in \{2^\lambda \mid 0 \leq \lambda \leq 30\})$
$a = 1$ means to replace the $x$-th gear with another one of radius $y$.
$a = 2$ means to assign angular velocity $y$ to the $x$-th gear and then determine the maximum angular velocity.
Output
Sample Input
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
4 3 4 1 4 16 2 1 2 4 1 2 3 2 1 4 1 1 16 1 2 4 2 4 4 1 4 16 4 3 5 2 16 4 8 2 1 2 1 2 3 1 1 4 2 1 4 1 3 8 2 1 16 1 4 1 2 1 8 |
Sample Output
1 2 3 4 5 6 |
Case #1: 1.386 Case #2: 2.773 3.466 2.773 |
Source
题意
思路
使用并查集维护共轴的齿轮关系。在每个齿轮连通块中选取一个参考齿轮,将所有的速度和半径对2取对数后,角速度之间差距就从倍数变成了差值,方便计算。从参考齿轮开始,进行dfs,并维护dfs序,优先dfs和这个齿轮共边的齿轮,并计算每个齿轮对于参考齿轮的角速度差,和这个齿轮u共边的齿轮v,他们的角速度都是都是比u的相对角速度快r[u]-r[v],其中r为半径,并且记每个v齿轮在树上的父亲为u。记录下这个dfs序的起止位置为edgeL[u],edgeR[u]。再dfs和这个齿轮共轴的齿轮,这些齿轮的角速度和u相同,并且记这些齿轮的在树上的父亲为不存在。记录这段dfs序列的起止位置为shaftL[u]和shaftR[u]。
询问的时候,先计算出参考齿轮的角速度,再求整个连通块内的最大值即可,区间应该为edgeL[u]~shaftR[u]。
修改分为两种情况。如果这个齿轮在树上没有父亲,那么修改他的半径,只会影响和他共边的齿轮以及共边齿轮连接的齿轮,区间为edgeL[u]+1~edgeR[u]。如果有父亲,则会影响他自己的角速度以及和他共轴齿轮及他们连接的齿轮,区间为edgeL[u]~edgeL[u],shaftL[u]~shaftR[u]。每次修改,对上述区间进行区间累加,维护最大值即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; struct EDGE { int to, next; EDGE(int to = 0, int next = 0): to(to), next(next) {} } edge[maxn * 2]; int head[maxn], edgecnt; int fa[maxn]; vector<int> shaft[maxn]; int edgeL[maxn], edgeR[maxn]; int shaftL[maxn], shaftR[maxn]; int d[maxn]; int radius[maxn]; int top[maxn]; int dfsclk; int velocity[maxn]; int targe[maxn]; int belong[maxn]; int n; void init() { dfsclk = 0; edgecnt = 0; memset(head, -1, sizeof(head)); memset(d, 0, sizeof(d)); memset(top, 0, sizeof(top)); memset(targe, 0, sizeof(targe)); for(int i = 0; i <= n ; i++) { shaft[i].clear(); fa[i] = i; } } void add(int s, int t) { edge[edgecnt] = EDGE(t, head[s]); head[s] = edgecnt++; } int findfa(int x) { if(x != fa[x]) fa[x] = findfa(fa[x]); return fa[x]; } void dfs(int u, int pre, int tp) { top[u] = tp; d[u] = pre; edgeL[u] = ++dfsclk; belong[dfsclk] = u; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if(v == pre) continue; velocity[v] = velocity[u] + (radius[u] - radius[v]); dfs(v, u, tp); } edgeR[u] = dfsclk; shaftL[u] = dfsclk + 1; int x = findfa(u); if(!targe[x]) { targe[x] = u; for(auto &v : shaft[x]) { if(v == u) continue; velocity[v] = velocity[u]; dfs(v, 0, tp); } } shaftR[u] = dfsclk; } int c[maxn * 4], mx[maxn * 4]; void build(int id, int L, int R) { c[id] = 0; if(L == R) mx[id] = velocity[belong[L]]; else { int mid = L + R >> 1; build(id << 1, L, mid); build(id << 1 | 1, mid + 1, R); mx[id] = max(mx[id << 1], mx[id << 1 | 1]); } } void pushdown(int id) { if(c[id]) { c[id << 1] += c[id]; c[id << 1 | 1] += c[id]; mx[id << 1] += c[id]; mx[id << 1 | 1] += c[id]; c[id] = 0; } } void modify(int id, int L, int R, int l, int r, int cc) { if(l <= L && R <= r) { c[id] += cc; mx[id] += cc; } else { pushdown(id); int mid = L + R >> 1; if(l <= mid) modify(id << 1, L, mid, l, r, cc); if(mid < r) modify(id << 1 | 1, mid + 1, R, l, r, cc); mx[id] = max(mx[id << 1], mx[id << 1 | 1]); } } int query(int id, int L, int R, int l, int r) { if(l <= L && R <= r) return mx[id]; else { pushdown(id); int mid = L + R >> 1; int ret = INT_MIN; if(l <= mid) ret = query(id << 1, L, mid, l, r); if(mid < r) ret = max(ret, query(id << 1 | 1, mid + 1, R, l, r)); return ret; } } void replace(int u, int r) { r = log2(r); if(d[u] == 0) { if(edgeL[u] < edgeR[u]) { modify(1, 1, n, edgeL[u] + 1, edgeR[u], r - radius[u]); } radius[u] = r; } else { if(shaftL[u] <= shaftR[u]) modify(1, 1, n, shaftL[u], shaftR[u], radius[u] - r); modify(1, 1, n, edgeL[u], edgeL[u], radius[u] - r); radius[u] = r; } } int query(int u, int v) { v = log2(v); int ru = query(1, 1, n, edgeL[u], edgeL[u]); v -= ru; int ret = query(1, 1, n, edgeL[top[u]], shaftR[top[u]]); ret += v; return ret; } struct FastIO { static const int S = 1310720; int wpos; char wbuf[S]; FastIO() : wpos(0) {} inline int xchar() { static char buf[S]; static int len = 0, pos = 0; if(pos == len) pos = 0, len = fread(buf, 1, S, stdin); if(pos == len) exit(0); return buf[pos ++]; } inline int xuint() { int c = xchar(), x = 0; while(c <= 32) c = xchar(); for(; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; return x; } inline int xint() { int s = 1, c = xchar(), x = 0; while(c <= 32) c = xchar(); if(c == '-') s = -1, c = xchar(); for(; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; return x * s; } inline void xstring(char *s) { int c = xchar(); while(c <= 32) c = xchar(); for(; c > 32; c = xchar()) * s++ = c; *s = 0; } inline void wchar(int x) { if(wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; wbuf[wpos ++] = x; } inline void wint(int x) { if(x < 0) wchar('-'), x = -x; char s[24]; int n = 0; while(x || !n) s[n ++] = '0' + x % 10, x /= 10; while(n--) wchar(s[n]); } inline void wstring(const char *s) { while(*s) wchar(*s++); } ~FastIO() { if(wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; } } io; int main() { //// freopen("1007.in", "r", stdin); //// freopen("out.out", "w", stdout); int m, q; int ks = 0; while(1) { n = io.xint(); m = io.xint(); q = io.xint(); init(); for(int i = 1; i <= n; i++) { radius[i] = io.xint(); radius[i] = log2(radius[i]); } while(m--) { int type = io.xint(), x = io.xint(), y = io.xint(); if(type == 1) { add(x, y); add(y, x); } else { int a = findfa(x); int b = findfa(y); fa[a] = b; } } for(int i = 1; i <= n; i++) { int x = findfa(i); shaft[x].push_back(i); } for(int i = 1; i <= n; i++) if(!top[i]) { velocity[i] = 0; dfs(i, 0, i); } build(1, 1, n); printf("Case #%d:\n", ++ks); while(q--) { int type = io.xint(), x = io.xint(), y = io.xint(); if(type == 1) { replace(x, y); } else { int ret = query(x, y); printf("%.3f\n", ret / log2(exp(1))); } } } return 0; } |