2015 年 蓝桥杯 A 组 C/C++ 第十题 灾后重建 【最小生成树 + LCA倍增 + 线段树维护区间max】
2018-03-11 15:29
429 查看
交题地址
详细复杂度做法解释
这是hard版本的.
AC Code
详细复杂度做法解释
这是hard版本的.
AC Code
const int maxn = 5e4+5; const int maxm = 2e5 + 5; int up[maxn][23], maxx[maxn][23]; int deep[maxn], dis[maxn]; int cnt, head[maxn]; int n, m, q; struct node { int to, next, w; }e[maxm<<1]; int fa[maxn], r[maxn]; void init() { Fill(head,-1); Fill(dis,0); Fill(up,0); Fill(deep,0); cnt = 0; for (int i = 1 ; i <= n ; i ++) { fa[i] = i; r[i] = 1; } } int Find(int x) { return fa[x] == x ? x : fa[x] = Find(fa[x]); } bool Un(int x, int y) { int fx = Find(x); int fy = Find(y); if (fx == fy) return false; if (r[fx] < r[fy]) swap(fx, fy); fa[fy] = fx; r[fx] += r[fy]; return true; } void add(int u, int v, int w) { e[cnt] = node{v, head[u], w}; head[u] = cnt++; } void dfs(int u,int fa,int d) { deep[u] = d + 1; for(int i = 1 ; i < 20 ; i ++) { up[u][i] = up[up[u][i-1]][i-1]; maxx[u][i] = max(maxx[up[u][i-1]][i-1], maxx[u][i-1]); } for(int i = head[u] ; ~i ; i = e[i].next) { int to = e[i].to; if(to == fa) continue; dis[to] = dis[u] + e[i].w; up[to][0] = u; maxx[to][0] = e[i].w; dfs(to, u, d+1); } } int LCA_BZ(int u,int v) { int mx = 0; if(deep[u] < deep[v]) swap(u,v); int k = deep[u] - deep[v]; for(int i = 0 ; i < 20 ; i ++) { if((1<<i) & k) { mx = max(mx, maxx[u][i]); u = up[u][i]; } } if(u != v) { for(int i = 19 ; i >= 0 ; i --) { if(up[u][i] != up[v][i]){ mx = max(mx, maxx[u][i]); mx = max(mx, maxx[v][i]); u = up[u][i]; v = up[v][i]; } } mx = max(mx, max(maxx[u][0], maxx[v][0])); u = up[u][0]; } return mx; } struct edge { int u, v, w; bool operator < (const edge& _) const { return w < _.w; } }s[maxm]; int a[maxn], ans[maxn*3]; struct Tree { int tl, tr, maxx; }tree[maxn<<2]; void pushup(int id) { tree[id].maxx = max(tree[id<<1].maxx , tree[id<<1|1].maxx); } void build(int id, int l, int r) { tree[id].tl = l, tree[id].tr = r; if(l == r){ tree[id].maxx = a[l]; return ; } int mid = (r+l)>>1; build(id<<1, l, mid); build(id<<1|1, mid+1, r); pushup(id); } void update(int id, int pos, int val) { int l = tree[id].tl, r = tree[id].tr; if(l == r){ tree[id].maxx = val; return ; } int mid = (l+r) >> 1; if(pos <= mid) update(id<<1, pos, val); else update(id<<1|1, pos, val); pushup(id); } int mx; void query(int id, int ql, int qr) { int l = tree[id].tl, r = tree[id].tr; if(ql <= l && r <= qr ){ mx = max(mx,tree[id].maxx); return ; } int mid = (l + r) >> 1; if(ql <= mid) query(id<<1, ql, qr); if(qr > mid) query(id<<1|1, ql, qr); } struct que { int l, r, p, c, id; bool operator < (const que& _) const { if (p == _.p) return c > _.c; return p > _.p; } int cal_ans() { int ans = 0; for (int i = (l-c+p-1)/p*p+c; i+p <= r ; i += p) { ans = max(ans, LCA_BZ(i, i+p)); } return ans; } void cal_build() { Fill(a, 0); for (int i = (!c)?p:c ; i + p <= n ; i += p) { a[i] = LCA_BZ(i, i+p); } // 因为只要是p, c相同的, 我们不会再建线段树,所以要更新到n // 而不是r. 因为询问的编号都相同, 所以可以直接求区间max. build(1, 1, n); } }qq[maxn*3]; void solve() { scanf("%d%d%d", &n, &m, &q); init(); for (int i = 1 ; i <= m ; i ++) { scanf("%d%d%d", &s[i].u, &s[i].v, &s[i].w); } sort(s+1, s+1+m); int num = 0; for (int i = 1 ; i <= m ; i ++) { if (Un(s[i].u, s[i].v)) { num++; add(s[i].u, s[i].v, s[i].w); add(s[i].v, s[i].u, s[i].w); } if (num == n - 1) break; } up[1][0] = 1; maxx[1][0] = 0; dfs(1, -1, 0); for (int i = 1 ; i <= q ; i ++) { scanf("%d%d%d%d", &qq[i].l, &qq[i].r, &qq[i].p, &qq[i].c); qq[i].id = i; } sort(qq+1, qq+1+q); int con = sqrt(n); for (int i = 1 ; i <= q ; i ++) { if (qq[i].p > con) ans[qq[i].id] = qq[i].cal_ans(); else { if (qq[i].p != qq[i-1].p || qq[i].c != qq[i-1].c) { qq[i].cal_build(); } mx = 0; query(1, qq[i].l, qq[i].r-qq[i].p); ans[qq[i].id] = mx; } } for (int i = 1 ; i <= q ; i ++) { printf("%d\n", ans[i]); } }
相关文章推荐
- codeforce 378 div 2 F —— Drivers Dissatisfaction (最小生成树,LCA,倍增)
- 【bzoj4242】水壶 BFS+最小生成树+倍增LCA
- 线段树区间修改 懒惰标记 维护和、最大值、最小值
- 蓝桥杯-【安慰奶牛】-最小生成树问题-【C++】
- 最小生成树和倍增法求lca(Uva11354Bond)
- codeforces 733 F. Drivers Dissatisfaction(最小生成树+lca+倍增去环)
- bzoj3732: Network(倍增LCA+最小生成树)
- HDU 4081 Qin Shi Huang's National Road System 最小生成树+倍增求LCA
- bzoj3732 Network 最小生成树+LCA+树上倍增
- UVa 11354 Bond 最小生成树+LCA倍增
- gym 101081 gym F. Auction of Services 最小生成树+倍增LCA
- 【bzoj3732】Network 最小生成树+倍增LCA
- UVA11354[Bond] 倍增求LCA+Kruskal求最小瓶颈生成树
- 东东的高速之旅 (线段树维护区间最小值)(模拟赛)
- 【BJOI2010】次小生成树-最小生成树+倍增LCA
- HYSBZ - 3732 最小生成树+倍增Lca
- Minimum spanning tree for each edge CodeForces - 609E(ST算法+树链剖分(或倍增LCA)+最小生成树)
- 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集
- UVa 11354 - Bond(最小生成树+倍增lca)
- 【UVa】11354 Bond 最小生成树,动态LCA,倍增思想