[线段树合并]
推荐黄嘉泰的线段树合并
HNOI永无乡
#include <stdio.h> #define maxn 100010 int n, m, id[maxn]; struct Edge{int to, nxt;}edge[maxn << 1]; int h[maxn], cnt; void add(int u, int v){ edge[++ cnt] = (Edge){v, h[u]}; h[u] = cnt; edge[++ cnt] = (Edge){u, h[v]}; h[v] = cnt; } int root[maxn], val[maxn]; bool vis[maxn]; int fa[maxn]; int getfa(int x){return x == fa[x] ? x : fa[x] = getfa(fa[x]);} #define TREE 5000010 int lc[TREE], rc[TREE], size[TREE], Size; void insert(int& rt, int l, int r, int x){ if(!rt)rt = ++ Size; size[rt] ++; if(l == r)return; int mid = l + r >> 1; if(x <= mid)insert(lc[rt], l, mid, x); else insert(rc[rt], mid+1, r, x); } int merge(int x, int y){ if(x == 0 || y == 0)return x + y; lc[x] = merge(lc[x], lc[y]); rc[x] = merge(rc[x], rc[y]); size[x] = size[lc[x]] + size[rc[x]]; return x; } int ask(int rt, int l, int r, int k){ if(l == r)return id[l]; int mid = l + r >> 1; if(k <= size[lc[rt]]) return ask(lc[rt], l, mid, k); k -= size[lc[rt]]; return ask(rc[rt], mid+1, r, k); } int main(){ scanf("%d%d", &n, &m); static int w[maxn]; for(int i = 1; i <= n; i ++) scanf("%d", &val[i]), id[val[i]] = i; int u, v; for(int i = 1; i <= n; i ++)fa[i] = i; for(int i = 1; i <= m; i ++){ scanf("%d%d", &u, &v); u = getfa(u), v = getfa(v); fa[getfa(v)] = getfa(u); } for(int i = 1; i <= n; i ++) insert(root[getfa(i)], 1, n, val[i]); int test; char cmd[2]; scanf("%d", &test); while(test --){ scanf("%s", cmd); if(cmd[0] == 'Q'){ scanf("%d%d", &u, &v), u = getfa(u); if(size[root[u]] < v){puts("-1");continue;} printf("%d\n", ask(root[u], 1, n, v)); } else{ scanf("%d%d", &u, &v); u = getfa(u), v = getfa(v); if(u == v)continue; root[u] = merge(root[u], root[v]); fa[getfa(v)] = getfa(u); } } return 0; }
[BZOJ 3702]二叉树
#include <bits/stdc++.h> #define maxn 400010 #define TREE 5000010 using namespace std; int n, son[maxn][2], w[maxn], root[maxn]; int cnt; int get_tree(){ int x = ++ cnt, a; scanf("%d", &a); if(a)w[x] = a; else{ son[x][0] = get_tree(); son[x][1] = get_tree(); } return x; } typedef long long ll; ll sum1, sum2, ans, sz[TREE]; int lc[TREE], rc[TREE], tr_cnt; int merge(int x, int y){ if(x == 0 || y == 0)return x + y; sum1 += sz[lc[x]] * sz[rc[y]]; sum2 += sz[lc[y]] * sz[rc[x]]; lc[x] = merge(lc[x], lc[y]); rc[x] = merge(rc[x], rc[y]); sz[x] = sz[lc[x]] + sz[rc[x]]; return x; } void insert(int &rt, int l, int r, int x){ rt = ++ tr_cnt; sz[rt] = 1; if(l == r)return; int mid = l + r >> 1; if(x <= mid) insert(lc[rt], l, mid, x); else insert(rc[rt], mid+1, r, x); } void dfs(int x){ if(son[x][0] && son[x][1]){ dfs(son[x][0]); dfs(son[x][1]); sum1 = sum2 = 0; root[x] = merge(root[son[x][0]], root[son[x][1]]); ans += min(sum1, sum2); } else insert(root[x], 1, n, w[x]); } int main(){ scanf("%d", &n); int root = get_tree(); dfs(root); printf("%lld\n", ans); return 0; }
[BZOJ 3307]雨天的尾巴
#include <bits/stdc++.h> #define maxn 100010 using namespace std; int n, m; struct Edge{ int to, nxt; }edge[maxn << 1]; int h[maxn], cnt; void add(int u, int v){ edge[++ cnt] = (Edge){v, h[u]}; h[u] = cnt; edge[++ cnt] = (Edge){u, h[v]}; h[v] = cnt; } int anc[maxn][20], fa[maxn], dep[maxn]; vector<int> hav[maxn]; void dfs(int u){ dep[u] = dep[fa[u]] + 1; for(int i = h[u]; i; i = edge[i].nxt){ int v = edge[i].to; if(v == fa[u])continue; fa[v] = anc[v][0] = u; dfs(v); } } int ask_LCA(int p, int q){ if(dep[p] < dep[q])swap(p, q); int log = 1; for(; 1 << log <= dep[p]; log ++);log --; for(int i = log; ~i; i --) if(dep[anc[p][i]] >= dep[q]) p = anc[p][i]; if(p == q)return p; for(int i = log; ~i; i --) if(anc[p][i] != anc[q][i]) p = anc[p][i], q = anc[q][i]; return fa[p]; } int ans[maxn]; int p[maxn], c;//离散 #define M 5000010 int pos[M], lc[M], rc[M], mx[M], root[maxn], size; void pushup(int o){ if(mx[lc[o]] >= mx[rc[o]]){ mx[o] = mx[lc[o]]; pos[o] = pos[lc[o]]; } else{ mx[o] = mx[rc[o]]; pos[o] = pos[rc[o]]; } } void insert(int& o, int l, int r, int val, int w){ if(o == 0){o = ++ size; pos[o] = l;} if(l == r){mx[o] += w;return;} int mid = l + r >> 1; if(val <= mid)insert(lc[o], l, mid, val, w); else insert(rc[o], mid+1, r, val, w); pushup(o); } int merge(int x, int y, int l, int r){ if(x == 0 || y == 0) return x + y; if(l == r){ mx[x] += mx[y]; pos[x] = l; } else{ int mid = l + r >> 1; lc[x] = merge(lc[x], lc[y], l, mid); rc[x] = merge(rc[x], rc[y], mid+1, r); pushup(x); }return x; } void solve(int u){ for(int i = h[u]; i; i = edge[i].nxt){ int v = edge[i].to; if(v == fa[u])continue; solve(v); root[u] = merge(root[u], root[v], 1, c); } for(int i = 0; i < hav[u].size(); i ++){ int nw = hav[u][i], flag = nw > 0 ? 1 : -1; nw = lower_bound(p + 1, p + 1 + c, abs(nw)) - p; insert(root[u], 1, c, nw, flag); } ans[u] = mx[root[u]] > 0 ? p[pos[root[u]]] : 0; } int main(){ scanf("%d%d", &n, &m); int u, v, w; for(int i = 1; i < n; i ++) scanf("%d%d", &u, &v), add(u, v); dfs(1); for(int j = 1; 1 << j <= n; j ++) for(int i = 1; i <= n; i ++) anc[i][j] = anc[anc[i][j-1]][j-1]; p[0] = 0; for(int i = 1; i <= m; i ++){ scanf("%d%d%d", &u, &v, &w); int LCA = ask_LCA(u, v); hav[u].push_back(w); hav[v].push_back(w); hav[LCA].push_back(-w); if(LCA != 1)hav[fa[LCA]].push_back(-w); p[++ c] = w; } sort(p + 1, p + 1 + c); c = unique(p + 1, p + 1 + c) - p - 1; solve(1); for(int i = 1; i <= n; i ++) printf("%d\n", ans[i]); return 0; }
给时光以生命,而不是给生命以时光。