题目链接:http://poj.org/problem?id=1177
呢个系我第一次做线段树离散化求矩形周长并,参考左Var Bob:^Joy关于线段树既文章。
8927215 | GZHU1006100106 | 1177 | Accepted | 1528K | 110MS | C++ | 3841B | 2011-07-19 11:12:09 |
#include
#include
#include
using namespace std;
#define MAXI 5005
#define INFI 10005
struct rect { int l, b, r, t; } rec[MAXI];
struct irec { int x, b, t, f; } xi[2 * MAXI];
int n, yi[2 * MAXI];
class segtree
{
protected :
struct node
{
node *ls, *rs;
int l, r, c, m, cc;
bool lb, rb;
} *root, *p;
public :
void make(node *&x)
{
x = new node;
x->ls = NULL;
x->rs = NULL;
x->l = x->r = x->c = x->m = x->cc = 0;
x->lb = x->rb = 0;
}
segtree() { root = NULL; }
int getm() { return root->m; }
int getcc() { return root->cc; }
void ins(int a, int b) { sins(root, a, b); }
void del(int a, int b) { sdel(root, a, b); }
void inti(int l, int r) { sint(root, l, r); }
void lata(node *&x, int a, int b)
{
if (x->c > 0)
{
x->m = yi[x->r] - yi[x->l];
x->lb = x->rb = x->cc = 1;
}
else if (x->c == 0 && x->l + 1 == x->r)
x->lb = x->rb = x->m = x->cc = 0;
else
{
x->lb = x->ls->lb;
x->rb = x->rs->rb;
x->m = x->ls->m + x->rs->m;
x->cc = x->ls->cc + x->rs->cc;
if (x->ls->rb == 1 && x->rs->lb == 1) x->cc--;
}
}
void sint(node *&x, int l, int r)
{
make(x);
x->l = l;
x->r = r;
if (l + 1 == r) return ;
sint(x->ls, l, (l + r) / 2);
sint(x->rs, (l + r) / 2, r);
}
void sins(node *&x, int a, int b)
{
int m = (x->l + x->r) / 2;
if (a <= x->l && x->r <= b)
x->c++;
else
{
if (a < m) sins(x->ls, a, b);
if (m < b) sins(x->rs, a, b);
}
lata(x, a, b);
}
void sdel(node *&x, int a, int b)
{
int m = (x->l + x->r) / 2;
if (a <= x->l && x->r <= b)
x->c--;
else
{
if (a < m) sdel(x->ls, a, b);
if (m < b) sdel(x->rs, a, b);
}
lata(x, a, b);
}
};
bool operator < (irec &a, irec &b)
{
if (a.x == b.x) return a.f < b.f;
else return a.x < b.x;
}
int bs(int key, int l, int r)
{
int m = (l + r) / 2;
if (yi[l] == key) return l;
if (yi[r] == key) return r;
if (yi[m] < key) return bs(key, m + 1, r);
if (yi[m] > key) return bs(key, l, m - 1);
return m;
}
int stat()
{
segtree zkl;
int i, sum = 0, cc = 0, tm = 0;
zkl.inti(0, 2 * n - 1);
for (i = 0; i < 2 * n; i++)
{
if (xi[i].f) zkl.del(xi[i].b, xi[i].t);
else zkl.ins(xi[i].b, xi[i].t);
sum += 2 * (xi[i].x - xi[i - 1].x) * cc;
sum += abs(zkl.getm() - tm);
tm = zkl.getm();
cc = zkl.getcc();
}
return sum;
}
int main()
{
int i, j;
while (scanf("%d", &n) != EOF)
{
//Discrete Begin
for (j = i = 0; i < n; i++)
{
scanf("%d%d%d%d",
&rec[i].l,
&rec[i].b,
&rec[i].r,
&rec[i].t);
yi[j++] = rec[i].b;
yi[j++] = rec[i].t;
}
sort(yi, yi + n * 2);
//Discrete End
//Event Sort Begin
for (j = i = 0; i < n; i++)
{
xi[j].x = rec[i].l;
xi[j].b = bs(rec[i].b, 0, 2 * n - 1);
xi[j].t = bs(rec[i].t, 0, 2 * n - 1);
xi[j++].f = 0;
xi[j].x = rec[i].r;
xi[j].b = xi[j - 1].b;
xi[j].t = xi[j - 1].t;
xi[j++].f = 1;
}
sort(xi, xi + n * 2);
//Event Sort End
printf("%d\n", stat());
}
return 0;
}