线段树合并
一般是对权值线段树进行操作
直接上代码
hnoi 2016 永无乡
#define MAXN 100010UL #include <cstdio> using namespace std; int n, m, num, Q, bg[MAXN], fa[MAXN], Rt[MAXN]; struct Seg { int ls, rs, val; } bn[20*MAXN]; int Get_fa(int x) { return fa[x]==x?fa[x]:fa[x] = Get_fa(fa[x]); } void Insert(int &rt, int l, int r, int pos) { if(!rt) rt = ++ num; if(l==r) { ++ bn[rt].val; return; } int mid = (l+r)>>1; if(pos<=mid) Insert(bn[rt].ls, l, mid, pos); else Insert(bn[rt].rs, mid+1, r, pos); bn[rt].val = bn[bn[rt].ls].val+bn[bn[rt].rs].val; return; } int Merge(int x, int y, int l, int r) { if(x==0||y==0) return x+y; if(l==r) bn[x].val += bn[y].val; else { bn[x].val += bn[y].val; int mid = (l+r)>>1; bn[x].ls = Merge(bn[x].ls, bn[y].ls, l, mid); bn[x].rs = Merge(bn[x].rs, bn[y].rs, mid+1, r); } return x; } int Ask(int rt, int l, int r, int k) { if(l==r) return l; int mid = (l+r)>>1; if(bn[bn[rt].ls].val>=k) return Ask(bn[rt].ls, l, mid, k); else return Ask(bn[rt].rs, mid+1, r, k-bn[bn[rt].ls].val); } int main() { int x, y; char s[10]; scanf("%d%d", &n, &m); for(int i = 1 ; i <= n ; ++ i) { scanf("%d", &x), Insert(Rt[i], 1, n, x); bg[x] = i, fa[i] = i; } for(int i = 1 ; i <= m ; ++ i) { scanf("%d%d", &x, &y); x = Get_fa(x), y = Get_fa(y); if(x!=y) fa[y] = x, Rt[x] = Merge(Rt[x], Rt[y], 1, n); } scanf("%d", &Q); for(int i = 1 ; i <= Q ; ++ i) { scanf("%s%d%d", s, &x, &y); if(*s=='B') { x = Get_fa(x), y = Get_fa(y); if(x!=y) fa[y] = x, Rt[x] = Merge(Rt[x], Rt[y], 1, n); } else { x = Get_fa(x); if(bn[Rt[x]].val<y) puts("-1"); else printf("%d\n", bg[Ask(Rt[x], 1, n, y)]); } } //while(1); return 0; }
二叉树
#define MAXN 5000010UL #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; int n, tot, num, w[MAXN], lc[MAXN], rc[MAXN], Rt[400010]; ll ret, cnt, ans; int Merge(int x, int y, int l, int r) { if(w[x]==0||w[y]==0) { if(w[x]||w[y]) { if(w[x]==0) ret += w[y]*cnt; else cnt += w[x]; } return x+y; } w[x] += w[y]; int mid = (l+r)>>1; lc[x] = Merge(lc[x], lc[y], l, mid); rc[x] = Merge(rc[x], rc[y], mid+1, r); return x; } void Insert(int &rt, int l, int r, int pos) { rt = ++ tot; w[rt] = 1; if(l==r) return; int mid = (l+r)>>1; if(pos<=mid) Insert(lc[rt], l, mid, pos); else Insert(rc[rt], mid+1, r, pos); return; } int Dfs(int x) { int nw; scanf("%d", &nw); if(nw>0) { Insert(Rt[x], 1, n, nw); return 1; } int ls, rs; int size_l = Dfs(ls = ++ num); Rt[x] = Rt[ls]; int size_r = Dfs(rs = ++ num); ret = cnt = 0; Rt[x] = Merge(Rt[x], Rt[rs], 1, n); ans += min(ret, 1ll*size_l*size_r-ret); return size_l+size_r; } int main() { scanf("%d", &n); Dfs(0); printf("%lld", ans); return 0; }
雨天的尾巴
#define MAXN 100010UL #include <cstring> #include <vector> #include <cstdio> #include <algorithm> using namespace std; int n, m, t, tot, num, Ans[MAXN], shu[MAXN], q[MAXN<<1][3], fa[MAXN][20], sn[MAXN], d[MAXN], Rt[MAXN]; vector <int> v1[MAXN]; vector <int> v2[MAXN]; struct ME { int zhi, id; friend bool operator < (ME x, ME y) { return x.zhi<y.zhi; } }st[MAXN<<1]; struct Seg { int ls, rs, mx, frm; } bn[5000010]; struct Edge { int hou, nt; } sg[MAXN<<1]; void Add(int x, int y) { sg[t] = (Edge){y, d[x]}, d[x] = t ++; sg[t] = (Edge){x, d[y]}, d[y] = t ++; return; } void Dfs_1(int x, int _fa, int dep) { fa[x][0] = _fa, sn[x] = dep; for(int i = 1 ; (1<<i) <= sn[x] ; ++ i) fa[x][i] = fa[fa[x][i-1]][i-1]; for(int i = d[x] ; i != -1 ; i = sg[i].nt) if(sg[i].hou!=_fa) Dfs_1(sg[i].hou, x, dep+1); return; } int Get_lca(int &x, int &y) { if(sn[x]<sn[y]) swap(x, y); int lg = 0; while((1<<lg+1)<=sn[x]) ++ lg; for(int i = lg ; i >= 0 ; -- i) if(sn[fa[x][i]]>=sn[y]) x = fa[x][i]; if(x==y) return x; for(int i = lg ; i >= 0 ; -- i) if(fa[x][i]!=fa[y][i]) x = fa[x][i], y = fa[y][i]; return fa[x][0]; } void Update(int rt) { bn[rt].mx = bn[bn[rt].ls].mx, bn[rt].frm = bn[bn[rt].ls].frm; if(bn[bn[rt].rs].mx>bn[rt].mx) bn[rt].mx = bn[bn[rt].rs].mx, bn[rt].frm = bn[bn[rt].rs].frm; return; } void Insert(int &rt, int l, int r, int pos, int k) { if(!rt) rt = ++ tot; if(l==r) { bn[rt].mx += k, bn[rt].frm = l; return; } int mid = (l+r)>>1; if(pos<=mid) Insert(bn[rt].ls, l, mid, pos, k); else Insert(bn[rt].rs, mid+1, r, pos, k); Update(rt); return; } int Merge(int x, int y, int l, int r) { if(x==0||y==0) return x+y; if(l==r) bn[x].mx += bn[y].mx, bn[x].frm = l; else { int mid = (l+r)>>1; bn[x].ls = Merge(bn[x].ls, bn[y].ls, l, mid); bn[x].rs = Merge(bn[x].rs, bn[y].rs, mid+1, r); Update(x); } return x; } void Dfs_2(int x, int _fa) { for(int i = d[x] ; i != -1 ; i = sg[i].nt) { if(sg[i].hou==_fa) continue; Dfs_2(sg[i].hou, x); Rt[x] = Merge(Rt[x], Rt[sg[i].hou], 1, num); } for(int i = 0, r = v1[x].size() ; i < r ; ++ i) Insert(Rt[x], 1, num, q[v1[x][i]][2], 1); if(bn[Rt[x]].mx>0) Ans[x] = shu[bn[Rt[x]].frm]; for(int i = 0, r = v2[x].size() ; i < r ; ++ i) Insert(Rt[x], 1, num, q[v2[x][i]][2], -1); return; } int main() { // freopen("ts.in", "r", stdin); // freopen("tail.out", "w", stdout); memset(d, -1, sizeof(d)); int x, y, z; scanf("%d%d", &n, &m); for(int i = 2 ; i <= n ; ++ i) scanf("%d%d", &x, &y), Add(x, y); Dfs_1(1, 0, 1); int cnt = m; for(int i = 1 ; i <= m ; ++ i) { scanf("%d%d%d", &x, &y, &z); if(sn[x]<sn[y]) swap(x, y); q[i][0] = y, q[i][1] = x; st[i].id = i, st[i].zhi = z; int anc = Get_lca(x, y); if(anc==q[i][0]) continue; ++ cnt, q[cnt][0] = anc, q[cnt][1] = q[i][0]; st[cnt].id = cnt, st[cnt].zhi = z; q[i][0] = x; } sort(st+1, st+cnt+1); num = 0; for(int i = 1 ; i <= cnt ; ++ i) { v1[q[i][1]].push_back(i), v2[q[i][0]].push_back(i); if((i==1)||st[i].zhi!=st[i-1].zhi) shu[++ num] = st[i].zhi; q[st[i].id][2] = num; } Dfs_2(1, 0); for(int i = 1 ; i <= n ; ++ i) printf("%d\n", Ans[i]); //while(1); return 0; }