一些离散化的题目

本文探讨了离散化技术在处理几何问题时的应用,包括如何利用平衡树、线段树等数据结构进行优化。特别介绍了hnoi2012三角形问题的稳定算法实现,通过双平衡树解决复杂度问题,并对比了手写treap在性能上的提升。文章总结了离散化操作中的常见错误,如在大量删除操作中使用map和set导致效率低下,以及一些脑残错误。最后,提供了两个离散化问题的代码示例,涉及矩阵覆盖和三角形问题,展示了离散化技术在实际问题解决中的重要性和实用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这几天做了一些离散化的题目。。。

话说这些题目一般都是先排序再建个线段树或者树状数组,或者直接拿平衡树维护一下,有时可以直接用上map或者set什么的。。。

而且很多都和几何有关。。。对于坐标的离散化很常见,一般有线段树套平衡树啊什么的。。。

还有个hnoi2012的triangle吧,我实在想不出什么复杂度靠谱的稳定算法,于是用了两个平衡树搞了一下,竟然A了。。。就是这样。。。

然后有了很多教训,比如有很多删除操作的时候千万别用map和set。。。这个慢到什么境界了。。。换手写treap速度翻三倍。。。

然后还犯了很多脑残错误,这里不贴了。。。

最后贴两道代码吧,奇长无比。。。

matrix:二维平面上依次画若干个实心矩形,每个矩形的形状要么是 A × B ,要么是 B × A 。求有多少个矩形没有被画在他之后的矩形覆盖。

写了各种二分什么的。。。常数较大,但至少不用开O2就可以只跑1s+了。。。

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <fstream>
#include <iostream>
using namespace std;

#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define PI M_PI
#define oo 0x13131313
#define iter iterator
#define PB push_back
#define PO pop_back
#define MP make_pair
#define fst first
#define snd second
#define cstr(a) (a).c_str()

#define FOR(i, j, k) for(i = (j); i <= (k); ++i)
#define ROF(i, j, k) for(i = (j); i >= (k); --i)
#define FER(e, d, u) for(e = d[u]; e; e = e->n)
#define FRE(i, a) for(i = (a).begin(); i != (a).end(); ++i)

typedef unsigned int uint;
typedef long long int64;
typedef unsigned long long uint64;
typedef long double real;

template<class T> inline bool minim(T &a, const T &b) {return b < a ? a = b, 1 : 0;}
template<class T> inline bool maxim(T &a, const T &b) {return b > a ? a = b, 1 : 0;}
template<class T> inline T sqr(const T &a) {return a * a;}

#define maxn 100005
#define random (seed *= oo)
#define updt(p) (p->size = p->c[0]->size + p->c[1]->size + 1)

struct elem
{
	elem *c[2];
	int v, key, size;
};

elem null[maxn*20], *et = null;
int temp, seed = 1;

void rotate(elem *&p, bool k)
{
	elem *q = p->c[!k];
	p->c[!k] = q->c[k], q->c[k] = p;
	updt(p), updt(q), p = q;
}

void insert(elem *&p)
{
	if (!p || p == null) *(p = ++et) = (elem){{null, null}, temp, random, 1};
	else if (temp == p->v) return;
	else if (temp < p->v) {
		insert(p->c[0]), updt(p);
		if (p->c[0]->key > p->key) rotate(p, 1);
	} else {
		insert(p->c[1]), updt(p);
		if (p->c[1]->key > p->key) rotate(p, 0);
	}
}

int lower_eq(elem *p, int v)
{
	if (!p) return 0;
	int ret = 0;
	for (; p != null; )
		if (p->v <= v) ret += p->c[0]->size + 1, p = p->c[1];
		else p = p->c[0];
	return ret;
}

int lower(elem *p, int v)
{
	if (!p) return 0;
	int ret = 0;
	for (; p != null; )
		if (p->v < v) ret += p->c[0]->size + 1, p = p->c[1];
		else p = p->c[0];
	return ret;
}

struct node
{
	node *s, *t;
	int l, r;
	elem *a;
};

node ns[maxn*4], *nt = ns, *rt[2];

node *build(int l, int r)
{
	node *p = ++nt; p->l = l, p->r = r;
	if (l == r) return p;
	p->s = build(l, (l + r) >> 1);
	p->t = build(((l + r) >> 1) + 1, r);
	return p;
}

int ll, rr, tx, ty;

void insert(node *p)
{
	temp = ty, insert(p->a);
	if (p->l == p->r) return;
	insert(tx <= p->s->r ? p->s : p->t);
}

bool query(node *p)
{
	if (ll <= p->l && p->r <= rr) return lower(p->a, ty) - lower_eq(p->a, tx) > 0;
	if (ll <= p->s->r && query(p->s)) return 1;
	if (p->t->l <= rr && query(p->t)) return 1;
	return 0;
}

int n, A, B;
int x[maxn], y[maxn], r[maxn];
int p[maxn];
int xx[maxn];

inline bool cmp(int i, int j) {return x[i] < x[j];}

inline void insert(int t)
{
	tx = xx[t], ty = y[t], insert(rt[r[t]]);
}

inline int upper(int t)
{
	int l = 1, r = n, mid;
	if (x[p[r]] < t) return 0;
	for (; l < r; )
		if (t < x[p[mid = (l + r) >> 1]]) r = mid;
		else l = mid + 1;
	return p[r];
}

inline int lower(int t)
{
	int l = 1, r = n, mid;
	if (x[p[r]] < t) return p[r];
	for (; l < r; )
		if (x[p[mid = (l + r) >> 1]] < t) l = mid + 1;
		else r = mid;
	return p[l - 1];
}

inline bool query(int t)
{
	int xt = x[t] + (r[t] ? A : B);
	int yt = y[t] + (r[t] ? B : A);
	if (!(rr = xx[lower(xt)])) return 0;
	ll = xx[upper(x[t] - B)], ty = yt;
	if (ll && ll <= rr) {
		tx = y[t] - A;
		if (query(rt[0])) return 1;
	}
	ll = xx[upper(x[t] - A)];
	if (ll && ll <= rr) {
		tx = y[t] - B;
		if (query(rt[1])) return 1;
	}
	return 0;
}

int ans;
bool del[maxn];

int main()
{
	freopen("matrix.in", "r", stdin);
	freopen("matrix.out", "w", stdout);

	int i, j;

	cin >> n >> A >> B;
	FOR(i, 1, n) {
		scanf("%d%d%d", x+i, y+i, r+i);
		p[i] = i;/* discretize x */
	}

	sort(p+1, p+n+1, cmp);
	for (i = j = 1; i <= n; ++i) {
		if (i > 1 && x[p[i]] != x[p[i-1]]) ++j;
		xx[p[i]] = j;
	}
	rt[0] = build(1, j);
	rt[1] = build(1, j);

	insert(n);
	ROF(i, n-1, 1) {
		if (query(i)) ++ans, del[i] = 1;
		insert(i);
	}

	cout << n - ans << endl;
	FOR(i, 1, n) if (!del[i]) printf("%d ", i);

	return 0;
}
triangle:乱搞。。。

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <fstream>
#include <iostream>
using namespace std;

#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define PI M_PI
#define oo 0x13131313
#define iter iterator
#define PB push_back
#define PO pop_back
#define MP make_pair
#define fst first
#define snd second
#define cstr(a) (a).c_str()

#define FOR(i, j, k) for(i = (j); i <= (k); ++i)
#define ROF(i, j, k) for(i = (j); i >= (k); --i)
#define FER(e, d, u) for(e = d[u]; e; e = e->n)
#define FRE(i, a) for(i = (a).begin(); i != (a).end(); ++i)

typedef unsigned int uint;
typedef long long int64;
typedef unsigned long long uint64;
typedef long double real;

template<class T> inline bool minim(T &a, const T &b) {return b < a ? a = b, 1 : 0;}
template<class T> inline bool maxim(T &a, const T &b) {return b > a ? a = b, 1 : 0;}
template<class T> inline T sqr(const T &a) {return a * a;}

#define maxn 100005

struct data {int v; data *n;};
data ds[maxn*5], *adj = ds;

map<int, data*> a, b;

int n, tot;
int x[maxn], y[maxn];
int d[maxn], q[maxn];

void add(map<int, data*> &a, int x, int v)
{
	data *&e = a[x];
	*(++adj) = (data){v, e}, e = adj;
}

bool check(int k)
{
	map<int, data*>::iter I; data *e;

	int u = y[k], v = u + d[k];
	int s, t;

	FRE(I, b) for (s = I->fst, e = I->snd; e; e = e->n) {
		t = s + q[e->v];
		if (s <= u && v <= t) return tot = n, 0;
		else if (s < u && u < t) ++tot, x[tot] = x[k] + t - u;
		else if (s < v && v < t) ++tot, x[tot] = x[k] + v - s;
	}
	FOR(n, n+1, tot) add(a, x[n], n);
	return n = tot, 1;
}

int main()
{
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);

	int i; cin >> n, tot = n;
	FOR(i, 1, n) scanf("%d%d%d", x+i, y+i, d+i), add(a, x[i], i);

	int pre, now; pre = now = 0;
	int before = -1;
	double ans = 0;
	map<int, data*>::iter I, J; data *e, *c, *cf;
	FRE(I, a) {
		pre = now, now = I->fst;
		int s, t, ret; s = t = ret = 0;
		FRE(J, b) {
			int tmp = J->fst;
			if (tmp > t) ret += t - s, s = t = tmp;
			for (cf = c = J->snd; c; cf = c, c = c->n)
				if (q[c->v] -= now - pre) maxim(t, tmp + q[c->v]);
				else if (c == J->snd) J->snd = c->n;
				else cf->n = c->n;
		}
		ret += t - s;
		if (~before) ans += (now - pre) * double(before + ret) / 2;

		for (e = I->snd; e; e = e->n)
			if (d[e->v] && check(e->v)) {
				add(b, y[e->v], e->v), q[e->v] = d[e->v];
				add(a, x[e->v] + d[e->v], e->v), d[e->v] = 0;
			}

		s = t = before = 0;
		FRE(J, b) {
			int tmp = J->fst;
			if (tmp > t) before += t - s, s = t = tmp;
			for (c = J->snd; c; c = c->n) maxim(t, tmp + q[c->v]);
		}
		before += t - s;
	}
	printf("%.1lf\n", ans);

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值