求面积:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 205;
struct Line
{
int st; //记录上下边
double s, e, x; //记录x的左右边
bool operator<(const Line &a) const
{
return x < a.x;
}
} line[N];
struct node
{
int cnt; //表示次数
double len;
} tree[N * 4];
void buildtree(int node, int start, int end)
{
tree[node].len = tree[node].cnt = 0;
if (start == end)
return;
int mid = (start + end) / 2;
buildtree(node * 2, start, mid);
buildtree(node * 2 + 1, mid + 1, end);
}
double lisan[N];
void pushup(int node, int start, int end)
{
if (tree[node].cnt) //如果有值的话 cnt>0
{
tree[node].len = lisan[end + 1] - lisan[start];
}
else if (start == end)
{
tree[node].len = 0; //更新操作
}
else
tree[node].len = tree[node << 1].len + tree[node << 1 | 1].len;
}
void update(int node, int start, int end, int L, int R, int val)
{
if (L > end || R < start)
return;
else if (start == end)
{
tree[node].cnt += val;
pushup(node, start, end);
return;
}
else if (start >= L && end <= R)
{
tree[node].cnt += val;
pushup(node, start, end);
return;
}
int mid = (start + end) >> 1;
// if (L <= mid)
update(node * 2, start, mid, L, R, val);
// if (R > mid)
update(node * 2 + 1, mid + 1, end, L, R, val);
pushup(node, start, end);
}
bool cmp(double a, double b)
{
return a < b;
}
int main()
{
int n, t = 1;
while (~scanf("%d", &n) && n)
{
int i, j = 1;
for (i = 1; i <= n; i++)
{
double x1, x2, yy1, y2;
scanf("%lf%lf%lf%lf", &x1, &yy1, &x2, &y2);
line[j].s = yy1, line[j].e = y2, line[j].x = x1, line[j].st = 1, lisan[j++] = yy1;
line[j].s = yy1, line[j].e = y2, line[j].x = x2, line[j].st = -1, lisan[j++] = y2;
}
sort(line + 1, line + 1 + n * 2);
sort(lisan + 1, lisan + 1 + n * 2, cmp);
int cnt = unique(lisan + 1, lisan + 1 + n * 2) - (lisan + 1) - 1;
buildtree(1, 1, cnt);
double ans = 0;
for (i = 1; i <= n * 2; i++) //从一开始是因为把line[1]的s和e更新
{
ans += tree[1].len * (line[i].x - line[i - 1].x);
int yl = lower_bound(lisan + 1, lisan + 1 + cnt, line[i].s) - lisan;
int yr = lower_bound(lisan + 1, lisan + 1 + cnt, line[i].e) - lisan - 1;
update(1, 1, cnt, yl, yr, line[i].st);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n", t++, ans);
}
return 0;
}
求周长(只扫描一遍,时间竟然多了)
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 500005;
struct Line
{
int st; //记录上下边
int h; //高度h
double s, e, y; //记录x的左右边
bool operator<(const Line &a) const
{
return y < a.y;
}
} line[N];
struct node
{
int l, r;
bool lc, rc;
int cnt; //表示次数
double len;
int num;
} tree[N * 4];
void buildtree(int node, int start, int end)
{
tree[node].l = start, tree[node].r = end;
tree[node].len = tree[node].cnt = tree[node].num = tree[node].lc = tree[node].rc = 0;
if (start == end)
return;
int mid = (start + end) / 2;
buildtree(node * 2, start, mid);
buildtree(node * 2 + 1, mid + 1, end);
}
double lisan[N];
void pushup(int node, int start, int end)
{
if (tree[node].cnt) //如果有值的话 cnt>0
{
tree[node].len = lisan[end + 1] - lisan[start];
tree[node].lc = tree[node].rc = 1;
tree[node].num = 1;
return;
}
if (start == end)
{
tree[node].lc = tree[node].rc = tree[node].num = 0;
tree[node].len = 0; //更新操作
}
else
{
tree[node].len = tree[node << 1].len + tree[node << 1 | 1].len;
tree[node].lc = tree[node << 1].lc;
tree[node].rc = tree[node << 1 | 1].rc;
tree[node].num = tree[node << 1].num + tree[node << 1 | 1].num - (tree[node << 1].rc & tree[node << 1 | 1].lc); // 如果都被覆盖则就是一个了。
}
}
void update(int node, int start, int end, int L, int R, int val)
{
if (L > end || R < start)
return;
else if (start == end)
{
tree[node].cnt += val;
pushup(node, start, end);
return;
}
else if (start >= L && end <= R)
{
tree[node].cnt += val;
pushup(node, start, end);
return;
}
int mid = (start + end) >> 1;
// if (L <= mid)
update(node * 2, start, mid, L, R, val);
// if (R > mid)
update(node * 2 + 1, mid + 1, end, L, R, val);
pushup(node, start, end);
}
bool cmp(double a, double b)
{
return a < b;
}
int main()
{
int n;
scanf("%d", &n);
int i, j = 1, jj = 1;
for (i = 1; i <= n; i++)
{
double x1, x2, yy1, y2;
scanf("%lf%lf%lf%lf", &x1, &yy1, &x2, &y2);
line[j].s = x1, line[j].e = x2, line[j].y = line[j].h = yy1, line[j].st = 1, lisan[j++] = x1;
line[j].s = x1, line[j].e = x2, line[j].y = line[j].h = y2, line[j].st = -1, lisan[j++] = x2;
}
sort(line + 1, line + 1 + n * 2);
sort(lisan + 1, lisan + 1 + n * 2, cmp);
int cnt = unique(lisan + 1, lisan + 1 + n * 2) - (lisan + 1) - 1;
buildtree(1, 1, cnt);
long long ans = 0;
for (i = 1; i <= n * 2; i++) //从一开始是因为把line[1]的s和e更新
{
int last = tree[1].len;
int xl = lower_bound(lisan + 1, lisan + 1 + cnt, line[i].s) - lisan;
int xr = lower_bound(lisan + 1, lisan + 1 + cnt, line[i].e) - lisan - 1;
update(1, 1, cnt, xl, xr, line[i].st);
ans += abs(last - tree[1].len); // 横线的
ans += (line[i + 1].h - line[i].h) * 2 * tree[1].num;
}
printf("%lld\n", ans);
return 0;
}
求周长(扫描两边的)(时间竟然比上面短, 但内存占用大)
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 500005;
struct Line
{
int st; //记录上下边
double s, e, y; //记录x的左右边
bool operator<(const Line &a) const
{
return y < a.y;
}
} line[N];
struct Line2
{
int st; //记录上下边
double s, e, x; //记录x的左右边
bool operator<(const Line2 &a) const
{
return x < a.x;
}
} line2[N];
struct node
{
int cnt; //表示次数
double len;
} tree[N * 4];
void buildtree(int node, int start, int end)
{
tree[node].len = tree[node].cnt = 0;
if (start == end)
return;
int mid = (start + end) / 2;
buildtree(node * 2, start, mid);
buildtree(node * 2 + 1, mid + 1, end);
}
double lisan[N], lisan2[N];
void pushup(int node, int start, int end)
{
if (tree[node].cnt) //如果有值的话 cnt>0
{
tree[node].len = lisan[end + 1] - lisan[start];
return;
}
if (start == end)
{
tree[node].len = 0; //更新操作
}
else
tree[node].len = tree[node << 1].len + tree[node << 1 | 1].len;
}
void update(int node, int start, int end, int L, int R, int val)
{
if (L > end || R < start)
return;
else if (start == end)
{
tree[node].cnt += val;
pushup(node, start, end);
return;
}
else if (start >= L && end <= R)
{
tree[node].cnt += val;
pushup(node, start, end);
return;
}
int mid = (start + end) >> 1;
// if (L <= mid)
update(node * 2, start, mid, L, R, val);
// if (R > mid)
update(node * 2 + 1, mid + 1, end, L, R, val);
pushup(node, start, end);
}
bool cmp(double a, double b)
{
return a < b;
}
int main()
{
int n;
scanf("%d", &n);
int i, j = 1, jj = 1;
for (i = 1; i <= n; i++)
{
double x1, x2, yy1, y2;
scanf("%lf%lf%lf%lf", &x1, &yy1, &x2, &y2);
line[j].s = x1, line[j].e = x2, line[j].y = yy1, line[j].st = 1, lisan[j++] = x1;
line[j].s = x1, line[j].e = x2, line[j].y = y2, line[j].st = -1, lisan[j++] = x2;
line2[jj].s = yy1, line2[jj].e = y2, line2[jj].x = x1, line2[jj].st = 1, lisan2[jj++] = yy1;
line2[jj].s = yy1, line2[jj].e = y2, line2[jj].x = x2, line2[jj].st = -1, lisan2[jj++] = y2;
}
sort(line + 1, line + 1 + n * 2);
sort(lisan + 1, lisan + 1 + n * 2, cmp);
int cnt = unique(lisan + 1, lisan + 1 + n * 2) - (lisan + 1) - 1;
buildtree(1, 1, cnt);
long long ans = 0;
for (i = 1; i <= n * 2; i++) //从一开始是因为把line[1]的s和e更新
{
int last = tree[1].len;
int xl = lower_bound(lisan + 1, lisan + 1 + cnt, line[i].s) - lisan;
int xr = lower_bound(lisan + 1, lisan + 1 + cnt, line[i].e) - lisan - 1;
update(1, 1, cnt, xl, xr, line[i].st);
ans += abs(last - tree[1].len);
}
// printf("%lld\n", ans);
sort(line2 + 1, line2 + 1 + n * 2);
sort(lisan2 + 1, lisan2 + 1 + n * 2, cmp);
for (i = 1; i <= n * 2; i++)
{
lisan[i] = lisan2[i];
}
cnt = unique(lisan + 1, lisan + 1 + n * 2) - (lisan + 1) - 1;
buildtree(1, 1, cnt);
for (i = 1; i <= n * 2; i++) //从一开始是因为把line2[1]的s和e更新
{
int last = tree[1].len;
int xl = lower_bound(lisan + 1, lisan + 1 + cnt, line2[i].s) - lisan;
int xr = lower_bound(lisan + 1, lisan + 1 + cnt, line2[i].e) - lisan - 1;
update(1, 1, cnt, xl, xr, line2[i].st);
ans += abs(last - tree[1].len);
}
printf("%lld\n", ans);
return 0;
}