这几天做了一些离散化的题目。。。
话说这些题目一般都是先排序再建个线段树或者树状数组,或者直接拿平衡树维护一下,有时可以直接用上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;
}