数据结构 1.0
扫描线
矩形面积并:
利用横线所截取的长度乘以纵向的差.
这里特别注意一下线段树中最底层表示的是一个点,但长度中需要维护线段.
所以不妨让线段树中的 $\mathrm{[l,r]}$ 区间实际维护 $\mathrm{[l, r+1)}$ 这条线段.
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200009
#define ll long long
#define pb push_back
#define ls now << 1
#define rs now << 1 | 1
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
struct Line {
int x1, x2, y, d;
Line(int x1 = 0, int x2 = 0, int y = 0, int d = 0):x1(x1), x2(x2), y(y), d(d) {}
}a[N];
int n , cnt , len[N << 2], A[N << 2], tot ;
struct data {
int sum, tag, l, r;
data() { sum = tag = l = r = 0; }
}s[N << 2];
void build(int l, int r, int now) {
s[now].l = l, s[now].r = r;
if(l == r) return ;
int mid = (l + r) >> 1;
build(l, mid, ls), build(mid + 1, r, rs);
}
void pushup(int now) {
if(s[now].tag)
len[now] = A[s[now].r + 1] - A[s[now].l];
else {
if(s[now].l != s[now].r)
len[now] = len[ls] + len[rs];
else len[now] = 0;
}
}
void update(int l, int r, int now, int L, int R, int v) {
if(l >= L && r <= R) {
s[now].tag += v;
pushup(now);
return ;
}
int mid = (l + r) >> 1;
if(L <= mid) update(l, mid, ls, L, R, v);
if(R > mid) update(mid + 1, r, rs, L, R, v);
pushup(now);
}
bool cmp(Line i, Line j) { return i.y < j.y; }
int main() {
// setIO("input");
scanf("%d", &n);
for(int i = 1; i <= n ; ++ i) {
int x[2], y[2];
scanf("%d%d%d%d", &x[0], &y[0], &x[1], &y[1]);
a[++ cnt] = Line(x[0], x[1], y[0], 1);
a[++ cnt] = Line(x[0], x[1], y[1], -1);
// 离散化横坐标即可.
A[++ tot] = x[0], A[++ tot] = x[1];
}
sort(A + 1, A + 1 + tot);
tot = unique(A + 1, A + 1 + tot) - A - 1;
for(int i = 1; i <= cnt ; ++ i) {
a[i].x1 = lower_bound(A + 1, A + 1 + tot, a[i].x1) - A;
a[i].x2 = lower_bound(A + 1, A + 1 + tot, a[i].x2) - A;
}
sort(a + 1, a + 1 + cnt, cmp);
// int pre = a[1].y;
build(1, tot , 1);
ll ans = 0;
for(int i = 1; i <= cnt ; ++ i) {
update(1, tot, 1, a[i].x1, a[i].x2 - 1, a[i].d);
ans += 1ll * len[1] * (a[i + 1].y - a[i].y);
}
printf("%lld", ans);
return 0;
}
平衡树
splay:
对于 $\mathrm{p}$ 节点进行操作后应将 $\mathrm{p}$ 旋转至根节点以保证时间复杂度.
但是旋转次数过多会导致效率降低,这里选择每 $10$ 次 $\mathrm{splay}$ 一次.
#include <bits/stdc++.h>
#define setIO(s) freopen(s".in","r", stdin)
using namespace std;
int times;
int judge() {
++ times;
return times % 10 == 0;
}
struct BST {
#define N 400009
#define ls s[x].ch[0]
#define rs s[x].ch[1]
#define inf 1000000000
struct data {
int f, v, size, ch[2];
void clr() {
f = v = size = ch[0] = ch[1] = 0;
}
}s[N];
int tot, sta[N], top, root;
int newnode() {
if(top) return sta[top -- ];
else return ++ tot;
}
void era(int x) {
sta[++ top] = x;
}
void pushup(int x) {
s[x].size = s[ls].size + s[rs].size + 1;
}
int get(int x) { return s[s[x].f].ch[1] == x; }
void rotate(int x) {
int old = s[x].f, fold = s[old].f, which = get(x);
if(fold)
s[fold].ch[s[fold].ch[1] == old] = x;
s[old].ch[which] = s[x].ch[which ^ 1];
if(s[old].ch[which])
s[s[old].ch[which]].f = old;
s[x].ch[which ^ 1] = old, s[old].f = x, s[x].f = fold;
pushup(old), pushup(x);
}
void splay(int x, int &tar) {
int o = s[tar].f;
// x 无论如何都会向上走一步.
for(int fa; (fa = s[x].f) != o; rotate(x))
if(s[fa].f != o)
rotate(get(fa) == get(x) ? fa : x);
tar = x;
}
// 加入两个空哨.
void init() {
int p = newnode(), q = newnode();
s[p].v = -inf, s[p].f = q, s[p].size = 1;
s[q].v = inf, s[q].ch[0] = p, s[q].size = 2;
root = q;
}
int ins(int &x, int fa, int v) {
if(!x) {
x = newnode();
s[x].v = v, s[x].size = 1, s[x].f = fa;
return x;
}
int p = ins(s[x].ch[v > s[x].v], x, v);
pushup(x);
return p ;
}
void Ins(int v) {
int p = ins(root, 0, v);
if(judge())
splay(p, root);
}
int get_pre(int x) {
int q = s[x].ch[0];
while(s[q].ch[1]) q = s[q].ch[1];
return q;
}
int get_aft(int x) {
int q = s[x].ch[1];
while(s[q].ch[0]) q = s[q].ch[0];
return q;
}
// 寻找最后一个小于等于 v 的.
int find(int x, int v) {
if(x == 0) return -1;
if(s[x].v > v)
return find(s[x].ch[0], v);
else {
int q = find(s[x].ch[1], v);
return q == -1 ? x : q;
}
}
void Del(int x) {
int p = find(root, x);
// 找到 p 了.
splay(p, root);
int pl = get_pre(p), pr = s[p].ch[1];
splay(pl, s[p].ch[0]);
s[pl].f = 0, s[pr].f = pl, s[pl].ch[1] = pr, pushup(pl);
root = pl;
s[p].clr(), era(p);
}
int get_num(int x, int kth) {
if(s[ls].size + 1 == kth)
return x;
if(kth <= s[ls].size)
return get_num(ls, kth);
else
return get_num(rs, kth - s[ls].size - 1);
}
int get_rank(int x) {
int p = find(root, x - 1);
splay(p, root);
return s[s[p].ch[0]].size + 1;
}
int query_num(int kth) {
int p = get_num(root, kth + 1);
if(judge())
splay(p, root);
return s[p].v;
}
int query_pre(int x) {
int p = find(root, x - 1);
if(judge())
splay(p, root);
return s[p].v;
}
int query_aft(int x) {
int p = find(root, x);
splay(p, root);
int q = get_aft(p);
splay(q, root);
return s[q].v;
}
#undef N
#undef ls
#undef rs
#undef inf
}T;
int main() {
int pp = clock();
// setIO("lim");
// freopen("input.out","w",stdout);
int Q;
scanf("%d", &Q);
T.init();
for(int i = 1; i <= Q; ++ i) {
int op, x, y, z;
scanf("%d%d", &op, &x);
if(op == 1) T.Ins(x);
if(op == 2) T.Del(x);
if(op == 3) printf("%d\n", T.get_rank(x));
if(op == 4) printf("%d\n", T.query_num(x));
if(op == 5) printf("%d\n", T.query_pre(x));
if(op == 6) printf("%d\n", T.query_aft(x));
}
// printf("%d\n", clock() - pp) ;
return 0;
}

浙公网安备 33010602011771号