1 条题解
-
0
首先我们现在改一下线段树保存的属性,我们用如下信息记录线段树的节点:
- l , r : 该节点代表的线段的左右端点坐标
2.len : 这个区间被覆盖的长度(即计算时的有效长度)
3.s : 表示这个区间被覆盖了几次
- lc , rc : 标记这个节点的左右两个端点是否被覆盖(0表示没有,1表示有)
5.num :这个区间有多少条不连续线段(这个区间被多少条线段覆盖)
这里的num涉及到竖线的计算,故解释一下,举几个例子:
若区间[0,10]被[1,2][4,5]覆盖,则num = 2
若区间[0,10]被[1,3][4,5]覆盖,则num = 1(两区间刚好连在一起)
若区间[0,10]被[1,5][2,6]覆盖,则num = 1(两区间连起来还是一段)
然后就可以计算竖线了:
竖线的长度 = 【下一条即将被扫到的横线的高度 - 现在扫到的横线的高度】2num
乘2是因为每条线段有两个端点;
看上图中棕色线段的竖线有4条,因为棕色的横线由2条线段组成
白色线段的竖线只有2条,因为白色的横线由1条线段组成(虽然这1条线段是由许多线段组合而成,但它依旧只算1条线段)
这样,依旧只扫一次就可以算出周长。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define ls i<<1 #define rs i<<1|1 #define m(i) ((q[i].l+q[i].r)>>1) typedef long long ll; const int N = 5007; const int X = 20007; const int inf = 1<<29; struct Edge{ int l,r; int h; int f; bool operator < (const Edge &a)const{ return h < a.h; } }e[N*2]; struct Node{ int l,r; int len; int s; bool lc,rc;//表示这个节点代表的区间左右两个端点是否被覆盖 int num;//这个区间有多少不连续到线段 }q[X*4]; void pushup(int i){ if(q[i].s){ q[i].len = q[i].r - q[i].l + 1; q[i].lc = q[i].rc = 1; q[i].num = 1; } else if(q[i].l == q[i].r){ q[i].len = 0; q[i].lc = q[i].rc = 0; q[i].num = 0; } else{ q[i].len = q[ls].len + q[rs].len; q[i].lc = q[ls].lc; q[i].rc = q[rs].rc; q[i].num = q[ls].num + q[rs].num - (q[ls].rc & q[rs].lc); } } void build(int i,int l,int r){ q[i].l = l; q[i].r = r; q[i].s = q[i].len = 0; q[i].lc = q[i].rc = q[i].num = 0; if(l == r) return; int mid = m(i); build(ls,l,mid); build(rs,mid+1,r); } void update(int i,int l,int r,int xx){ if(l == q[i].l && q[i].r == r){ q[i].s += xx; pushup(i); return; } int mid = m(i); if(r <= mid) update(ls,l,r,xx); else if(l > mid) update(rs,l,r,xx); else{ update(ls,l,mid,xx); update(rs,mid+1,r,xx); } pushup(i); } int main(){ int n; while(scanf("%d",&n) != EOF){ int x1,x2,y1,y2,mx = -inf,mn = inf; int tot = 0; for(int i = 0; i < n; i++){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); mx = max(mx,max(x1,x2)); mn = min(mn,min(x1,x2)); Edge &t1 = e[tot]; Edge &t2 = e[tot+1]; t1.l = t2.l = x1; t1.r = t2.r = x2; t1.h = y1; t1.f = 1; t2.h = y2; t2.f = -1; tot += 2; } sort(e,e+tot); //数据小不用离散化 int ans = 0; int last = 0; build(1,mn,mx-1); for(int i = 0; i < tot; i++){ update(1,e[i].l,e[i].r-1,e[i].f); ans += abs(q[1].len - last); ans += (e[i+1].h - e[i].h) * 2 * q[1].num; last = q[1].len; } printf("%d\n",ans); } return 0; }
- 1
信息
- ID
- 178
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者