题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1828
分析:与面积不同的地方是还要记录竖的边有几个(num记录),并且当边界重合的时候需要合并(用lbd和rbd表示边界来辅助)
线段树操作:update:区间增减 query:直接取根节点的值
#include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 10007 #define inf 0x3f3f3f3f #define N 20015 #define FILL(a,b) (memset(a,b,sizeof(a))) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; struct line { int l,r,h,d; line(){} line(int l,int r,int h,int d):l(l),r(r),h(h),d(d){} bool operator<(const line &a)const { return h<a.h; } }s[N]; int sum[N<<2],col[N<<2],num[N<<2]; int lbd[N<<2],rbd[N<<2]; void Pushup(int l,int r,int rt) { if(col[rt]) { lbd[rt]=1;rbd[rt]=1; num[rt]=2; sum[rt]=r-l+1; } else if(l==r) { num[rt]=0;sum[rt]=0; lbd[rt]=0;rbd[rt]=0; } else { lbd[rt]=lbd[rt<<1];rbd[rt]=rbd[rt<<1|1]; sum[rt]=sum[rt<<1]+sum[rt<<1|1]; num[rt]=num[rt<<1]+num[rt<<1|1]; if(rbd[rt<<1]&&lbd[rt<<1|1])num[rt]-=2; } } void update(int L,int R,int d,int l,int r,int rt) { if(L<=l&&r<=R) { col[rt]+=d; Pushup(l,r,rt); return; } int m=(l+r)>>1; if(L<=m)update(L,R,d,lson); if(m<R)update(L,R,d,rson); Pushup(l,r,rt); } int main() { int L,R,n; int x1,x2,y1,y2; while(scanf("%d",&n)>0) { int m=0; L=inf;R=-inf; for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); L=min(L,x1);R=max(R,x2); s[m++]=line(x1,x2,y1,1); s[m++]=line(x1,x2,y2,-1); } sort(s,s+m); int ans=0,last=0; for(int i=0;i<m;i++) { update(s[i].l,s[i].r-1,s[i].d,L,R-1,1); ans+=num[1]*(s[i+1].h-s[i].h); ans+=abs(sum[1]-last); last=sum[1]; } printf("%d\n",ans); } }