# 线段树合并 总结

void insert(int &i, int l, int r, int x) {
i = ++T;
if(l == r) {
sum[i]++;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) insert(lc[i], l, mid, x) ;
if(x > mid) insert(rc[i], mid + 1, r, x) ;
update(i);
}

int merge(int x, int y) {
if(!x) return y;
if(!y) return x;
sum[x] += sum[y] ;//合并区间信息
lc[x] = merge(lc[x], lc[y]) ;
rc[x] = merge(rc[x], rc[y]) ;
return x;//相当于删除另外一个结点
}

1.洛谷P3605

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int p[N], a[N], ans[N] ;
int tre[N * 20], lc[N * 20], rc[N * 20], rt[N];
int n, T;
struct Edge{
int v, next ;
}e[N];
void adde(int u, int v) {
}
void insert(int &i, int l, int r, int x) {
if(r < l) return ;
i = ++T;
if(l == r) {
tre[i]++ ;
return ;
}
int mid = (l + r) >> 1 ;
if(x <= mid) insert(lc[i], l, mid, x) ;
if(x > mid) insert(rc[i], mid + 1, r, x) ;
tre[i] = tre[lc[i]] + tre[rc[i]] ;
}
int query(int root, int l, int r, int x) {
if(!root) return 0;
if(l >= x) return tre[root];
int ans = 0;
int mid = (l + r) >> 1;
if(mid >= x) ans += query(lc[root], l, mid, x) ;
ans += query(rc[root], mid + 1, r, x) ;
return ans ;
}
int merge(int x, int y) {
if(!x) return y;
if(!y) return x;
lc[x] = merge(lc[x], lc[y]) ;
rc[x] = merge(rc[x], rc[y]) ;
tre[x] = tre[lc[x]] + tre[rc[x]] ;
return x;
}
void dfs(int u) {
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v ;
dfs(v) ;
rt[u] = merge(rt[u], rt[v]) ;
}
ans[u] = query(rt[u], 1, n, a[u] + 1) ;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) cin >> p[i] , a[i] = p[i];
sort(p + 1, p + n + 1);
int D = unique(p + 1, p + n + 1) - p - 1;
for(int i = 1; i <= n; i++) a[i] = lower_bound(p + 1, p + D + 1, a[i]) - p;
for(int i = 2; i <= n; i++) {
int x;cin >> x;
}
for(int i = 1; i <= n; i++) insert(rt[i], 1, n, a[i]) ;
dfs(1) ;
for(int i = 1; i <= n; i++) cout << ans[i] << '\n';
return 0;
}
View Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int p[N], a[N], ans[N] ;
int c[N];
int n, T;
struct Edge{
int v, next ;
}e[N];
void adde(int u, int v) {
}
int lowbit(int x) {
return x & (-x) ;
}
void update(int p, int v) {
for(int i = p ; i < N; i += lowbit(i)) c[i] += v ;
}
int query(int p) {
int ans = 0 ;
for(int i = p ; i > 0 ; i -= lowbit(i)) ans += c[i] ;
return ans ;
}
void dfs(int u) {
update(a[u], 1);
int sum1 = query(N - 1) - query(a[u]) ;
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
dfs(v) ;
}
int sum2 = query(N - 1) - query(a[u]) ;
ans[u] = sum2 - sum1 ;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) cin >> p[i] , a[i] = p[i];
sort(p + 1, p + n + 1);
int D = unique(p + 1, p + n + 1) - p - 1;
for(int i = 1; i <= n; i++) a[i] = lower_bound(p + 1, p + D + 1, a[i]) - p;
for(int i = 2; i <= n; i++) {
int x;cin >> x;
}
dfs(1) ;
for(int i = 1; i <= n; i++) cout << ans[i] << '\n';
return 0;
}
View Code

2.洛谷P3224

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
int n, m;
int v[N], f[N], rt[N], lc[N * 20], rc[N * 20], sum[N * 20], rk[N *20];
int T ;
int find(int x) {
return f[x] == x ? f[x] : f[x] = find(f[x]) ;
}
void insert(int &i, int l, int r, int x) {
if(r < l) return ;
i = ++T;
if(l == r) {
sum[i]++;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) insert(lc[i], l, mid, x) ;
if(x > mid) insert(rc[i], mid + 1, r, x) ;
sum[i] = sum[lc[i]] + sum[rc[i]] ;
}
int merge(int x, int y, int l, int r) {
if(!x) return y;
if(!y) return x;
if(l == r) {
sum[x] += sum[y] ;
return x;
}
int mid = (l + r) >> 1;
lc[x] = merge(lc[x], lc[y], l, mid) ;
rc[x] = merge(rc[x], rc[y], mid + 1, r) ;
sum[x] = sum[lc[x]] + sum[rc[x]] ;
return x;
}
int query(int root, int l, int r, int k) {
if(l == r) return l ;
int mid = (l + r) >> 1;
if(sum[lc[root]] >= k) return query(lc[root], l, mid, k) ;
else return query(rc[root], mid + 1 ,r ,k - sum[lc[root]]) ;
}
int main() {
scanf("%d%d",&n, &m) ;
for(int i = 1; i <= n; i++) scanf("%d", &v[i]), rk[v[i]] = i;
for(int i = 1; i <= n; i++) f[i] = i;
for(int i = 1; i <= n; i++) insert(rt[i], 1, n, v[i]) ;
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d",&u, &v);
int fx = find(u), fy = find(v) ;
if(fx != fy) {
rt[fx] = merge(rt[fx], rt[fy], 1, n) ;
f[fy] = fx;
}
}
int q ;
scanf("%d", &q) ;
char s[2] ;
while(q--) {
int u, v;
scanf("%s%d%d",s, &u, &v);
if(s[0] == 'Q') {
int fx = find(u);
if(sum[rt[fx]] < v) {
printf("-1\n");
continue ;
}
int ans = query(rt[fx], 1, n, v) ;
printf("%d\n", rk[ans]);
}else {
int fx = find(u), fy = find(v) ;
if(fx != fy) {
rt[fx] = merge(rt[fx], rt[fy], 1, n) ;
f[fy] = fx;
}
}
}
return 0;
}
View Code

3.洛谷P3521

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int n ;
ll sum[N * 22] ;
int lc[N * 22], rc[N * 22], rt[N * 22];
int T;
ll ans, sum1, sum2;
int merge(int x, int y) {
if(!x) return y;
if(!y) return x;
sum[x] += sum[y] ;
sum1 += sum[lc[x]] * sum[rc[y]] ;
sum2 += sum[rc[x]] * sum[lc[y]] ;
lc[x] = merge(lc[x], lc[y]) ;
rc[x] = merge(rc[x], rc[y]) ;
return x;
}
void insert(int &i, int l, int r, int x) {
i = ++T;
if(l == r) {
sum[i]++;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) insert(lc[i], l, mid, x) ;
if(x > mid) insert(rc[i], mid + 1, r, x) ;
sum[i] = sum[lc[i]] + sum[rc[i]] ;
}
void dfs(int &p) {
int x, ls, rs;p = 0;
cin >> x ;
if(x == 0) {
dfs(ls);
dfs(rs);
sum1 = sum2 = 0;
p = ls ;
p = merge(ls, rs) ;
ans += min(sum1, sum2) ;
}
else insert(rt[x], 1, n, x), p = rt[x];
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
int t = 0;
dfs(t);
cout << ans ;
return 0 ;
}
View Code

posted @ 2019-04-16 22:36  heyuhhh  阅读(2531)  评论(3编辑  收藏  举报