hdu 1828--线段树扫描线

http://acm.hdu.edu.cn/showproblem.php?pid=1828

题意:矩形周长并

思路:与面积不同的地方是还要记录竖的边有几个(hsum记录),并且当边界重合的时候需要合并(用lbd和rbd表示边界来辅助)

复制代码
View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 55555
 8 #define lson l,m,rt<<1
 9 #define rson m+1,r,rt<<1|1
10 int hsum[maxn<<2],len[maxn<<2],flag[maxn<<2],lbd[maxn<<2],rbd[maxn<<2];
11 struct node{
12     int l,r,h,s;
13     node(){}
14     node(int a,int b,int c,int d):l(a),r(b),h(c),s(d){}
15     bool operator < (const node &cmp) const    {
16         if(cmp.h==h) return s>cmp.s;
17         return h<cmp.h;
18     }
19 }ss[maxn];
20 int max(int a,int b)
21 {
22     return a>b?a:b;
23 }
24 int min(int a,int b)
25 {
26     return a<b?a:b;
27 }
28 void Pushup(int l,int r,int rt)
29 {
30     if(flag[rt])
31     {
32         lbd[rt]=rbd[rt]=1;
33         hsum[rt]=2;
34         len[rt]=r-l+1;
35     }
36     else if(l==r)
37     {
38         len[rt]=hsum[rt]=lbd[rt]=rbd[rt]=0;
39     }
40     else
41     {
42         lbd[rt]=lbd[rt<<1];
43         rbd[rt]=rbd[rt<<1|1];
44         len[rt]=len[rt<<1]+len[rt<<1|1];
45         hsum[rt]=hsum[rt<<1]+hsum[rt<<1|1];
46         if(lbd[rt<<1|1]&&rbd[rt<<1]) hsum[rt]-=2;
47     }
48 }
49 void update(int L,int R,int w,int l,int r,int rt)
50 {
51     if(L<=l&&r<=R)
52     {
53         flag[rt]+=w;
54         Pushup(l,r,rt);
55         return;
56     }
57     int m=(l+r)>>1;
58     if(L<=m) update(L,R,w,lson);
59     if(R>m) update(L,R,w,rson);
60     Pushup(l,r,rt);
61 }
62 int main()
63 {
64     int t,a,b,c,d;
65     while(~scanf("%d",&t))
66     {
67         int m=0;
68         int lrd=10000,rrd=-10000;
69         while(t--)
70         {
71             scanf("%d %d %d %d",&a,&b,&c,&d);
72             ss[m++]=node(a,c,b,1);
73             ss[m++]=node(a,c,d,-1);
74             lrd=min(lrd,c);
75             lrd=min(lrd,a);
76             rrd=max(rrd,c);
77             rrd=max(rrd,a);
78         }
79         sort(ss,ss+m);
80         int ret=0,last=0;
81         for(int i=0;i<m;i++)
82         {
83             if(ss[i].l<ss[i].r) update(ss[i].l,ss[i].r-1,ss[i].s,lrd,rrd-1,1);
84             ret+=hsum[1]*(ss[i+1].h-ss[i].h);
85             ret+=abs(len[1]-last);
86             last=len[1];
87         }
88         printf("%d\n",ret);
89     }
90     return 0;
91 }
复制代码

 

posted on 2013-02-19 13:53  acoderworld  阅读(76)  评论(0)    收藏  举报

编辑推荐:
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 我在厂里搞 wine 的日子
阅读排行:
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 只需一行命令,Win11秒变Linux开发主机!
· 上周热点回顾(7.7-7.13)
· 也是出息了,业务代码里面也用上算法了。
< 2025年7月 >
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9

导航

统计

点击右上角即可分享
微信分享提示