[线段树扫描线][USACO5.5]矩形周长Picture

墙上贴着许多形状相同的海报、照片。它们的边都是水平和垂直的。每个矩形图片可能部分或全部的覆盖了其他图片。所有矩形合并后的边长称为周长。

所有矩形的边界。所有矩形顶点的坐标都是整数。

输入文件的第一行是一个整数N(0<=N<5000),表示有多少个矩形。接下来N行给出了每一个矩形左下角坐标和右上角坐标(所有坐标的数值范围都在-10000到10000之间)。

输出文件只有一个正整数,表示所有矩形的周长。

 

题解

  线段树扫描线  https://www.luogu.org/problemnew/solution/P1856

 维护的东西非常巧妙  注意覆盖标记不下传  因为只查询根节点

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=10000+5;
 6 int n;
 7 struct edge{int x,y,h,c;}a[N];
 8 bool cmp(edge p,edge q) {return p.h<q.h || (p.h==q.h&& p.c>q.c);}
 9 
10 int tot,b[N];
11 inline int hehe(int x) {return lower_bound(b+1,b+tot+1,x)-b;} 
12 
13 struct point{int l,r,cov,cnt,len; bool lf,rf; }t[4*N];
14 inline void pushup(int i,int l,int r)
15  {if(t[i].cov)
16      {t[i].len=t[i].r-t[i].l;
17       t[i].lf=t[i].rf=1;
18       t[i].cnt=1;
19      }
20   else 
21      {t[i].len=t[2*i].len+t[2*i+1].len;
22       t[i].lf=t[2*i].lf; t[i].rf=t[2*i+1].rf;
23       t[i].cnt=t[2*i].cnt+t[2*i+1].cnt;
24       if(t[2*i].rf && t[2*i+1].lf) t[i].cnt--;
25      }
26  }
27 void build(int i,int l,int r)
28  {t[i].l=b[l]; t[i].r=b[r+1];
29   if(l==r) return;
30   int mid=l+r>>1;
31   build(2*i,l,mid); build(2*i+1,mid+1,r);    
32  }
33 void change(int i,int l,int r,int p,int q,int v)
34  {if(p<=l && r<=q) {t[i].cov+=v; pushup(i,l,r); return;}
35   int mid=l+r>>1;
36   if(p<=mid) change(2*i,  l,  mid,p,q,v);
37   if(mid<q)     change(2*i+1,mid+1,r,p,q,v);
38   pushup(i,l,r);
39  } 
40 int main() 
41 {
42  scanf("%d",&n); int x1,y1,x2,y2;
43     
44  for(int i=1;i<=n;i++)    
45   { scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
46     a[2*i-1].x=a[2*i].x=x1; a[2*i-1].y=a[2*i].y=x2;
47     a[2*i-1].h=y1; a[2*i].h=y2;
48     a[2*i-1].c=1;  a[2*i].c=-1;
49     b[++tot]=x1; b[++tot]=x2;
50   }    
51  sort(a+1,a+2*n+1,cmp);    
52      
53  sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1;    
54 
55  build(1,1,tot-1); int ans=0,last=0;
56  
57  for(int i=1;i<=2*n;i++)
58   { change(1,1,tot-1,hehe(a[i].x),hehe(a[i].y)-1,a[i].c);
59       
60       ans+=2*t[1].cnt*(a[i+1].h-a[i].h)+abs(t[1].len-last);
61       last=t[1].len;
62   }
63  printf("%d\n",ans); 
64 return 0;    
65 }

 

转载于:https://www.cnblogs.com/YuXiaoze/p/11420758.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值