一般是对权值线段树进行操作
直接上代码
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;
}