添加lb[],rb[]数组,来标记竖边。添加num,来计算竖边的个数,因为计算周长的时候,未覆盖的竖边都要加
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 10100 bool lb[maxn<<2],rb[maxn<<2]; struct seg { int l,r,h; int f; }s[maxn]; struct node { int cnt; int num; int len; }tree[maxn<<2]; int mark[maxn<<2]; int min(int x,int y) { return x<y?x:y; } int max(int x,int y) { return x>y?x:y; } bool cmp(seg a,seg b) { return a.h<b.h; } void getlen(int l,int r,int rt) { if(tree[rt].cnt) { lb[rt]=rb[rt]=true;//标记竖边是否被使用 tree[rt].len=mark[r+1]-mark[l]; tree[rt].num=2; } else if(l==r) tree[rt].len=tree[rt].num=lb[rt]=rb[rt]=0; else { tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len; tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num; lb[rt]=lb[rt<<1];rb[rt]=rb[rt<<1|1]; if(rb[rt<<1]&&lb[rt<<1|1])//左孩子的右边和右孩子左边已经被使用 那这2条就不需要加 tree[rt].num-=2; } } void updata(int L,int R,int c,int l,int r,int rt) { if(L<=l&&R>=r) { tree[rt].cnt+=c; getlen(l,r,rt); return ; } int m=(l+r)/2; if(m>=L) updata(L,R,c,lson); if(R>m) updata(L,R,c,rson); getlen(l,r,rt); } int find(int val,int num) { int l,r,m; l=0;r=num; while(l<=r) { m=(l+r)/2; if(val==mark[m]) return m; else if(val>mark[m]) l=m+1; else r=m-1; } return -1; } int main() { int i,n,m,L,R; int x1,x2,y1,y2; while(scanf("%d",&n)!=EOF) { m=0; L=999999; R=-999999; memset(s,0,sizeof(s)); for(i=0;i<n;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); s[m].l=x1;s[m].r=x2;s[m].h=y1;mark[m]=x1;s[m++].f=1; s[m].l=x1;s[m].r=x2;s[m].h=y2;mark[m]=x2;s[m++].f=-1; } sort(mark,mark+m); int k=1; for(i=1;i<m;i++) { if(mark[i]!=mark[i-1]) mark[k++]=mark[i]; } memset(tree,0,sizeof(tree)); memset(lb,false,sizeof(lb)); memset(rb,false,sizeof(rb)); sort(s,s+m,cmp); int ans=0,past=0; for(i=0;i<m;i++) { int ll=find(s[i].l,k-1); int rr=find(s[i].r,k-1)-1; updata(ll,rr,s[i].f,0,k-1,1); ans+=tree[1].num*(s[i+1].h-s[i].h); ans+=abs(tree[1].len-past); past=tree[1].len; } printf("%d\n",ans); } }
时间: 2024-10-09 22:09:51