码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1828 Picture (线段树:扫描线周长)

时间:2018-09-24 23:28:51      阅读:362      评论:0      收藏:0      [点我收藏+]

标签:void   扫描   algo   print   str   long   shu   using   答案   

依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长。

容易发现,扫描线中的某一条横边对答案的贡献。

其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值

然后横着竖着都做一遍就行了

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #define N 10010
  5 #define ll long long
  6 using namespace std;
  7 
  8 int n,sz;
  9 int a[N],cnt[N<<2],sum[N<<2];
 10 struct SQU{
 11     int a1,b1,a2,b2;
 12 }q[N];
 13 struct node{
 14     int l,r,la,ra,h,f;
 15 }sc[N];
 16 int cmp1(node s1,node s2){
 17     if(s1.h!=s2.h) return s1.h<s2.h;
 18     else return s1.f>s2.f;
 19 }
 20 void pushup(int l,int r,int rt)
 21 {
 22     if(cnt[rt]>0) sum[rt]=a[r+1]-a[l];
 23     else if(l==r) sum[rt]=0;
 24     else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 25 }
 26 void update(int L,int R,int l,int r,int rt,int w)
 27 {
 28     if(L<=l&&r<=R) 
 29     {
 30         cnt[rt]+=w;
 31         pushup(l,r,rt);
 32         return;
 33     }
 34     int mid=(l+r)>>1;
 35     if(L<=mid) update(L,R,l,mid,rt<<1,w);
 36     if(R>mid) update(L,R,mid+1,r,rt<<1|1,w);
 37     pushup(l,r,rt);
 38 }
 39 void clr()
 40 {
 41     memset(a,0,sizeof(a));
 42     memset(sc,0,sizeof(sc));
 43     memset(cnt,0,sizeof(cnt));
 44     memset(sum,0,sizeof(sum));
 45 }
 46 int solvex()
 47 {   
 48     int ans=0,lst=0;
 49     for(int i=1;i<=n;i++)
 50     {
 51         a[2*i-1]=q[i].a1,a[2*i]=q[i].a2;
 52         sc[2*i-1].l=q[i].a1,sc[2*i].l=q[i].a1;
 53         sc[2*i-1].r=q[i].a2,sc[2*i].r=q[i].a2;
 54         sc[2*i-1].h=q[i].b1,sc[2*i].h=q[i].b2;
 55         sc[2*i-1].f=1,sc[2*i].f=-1;
 56     }
 57     sort(a+1,a+2*n+1);
 58     sz=unique(a+1,a+2*n+1)-(a+1);
 59     sort(sc+1,sc+2*n+1,cmp1);
 60     for(int i=1;i<=2*n;i++)
 61     {
 62         int la=lower_bound(a+1,a+sz+1,sc[i].l)-a;
 63         int ra=lower_bound(a+1,a+sz+1,sc[i].r)-a;
 64         lst=sum[1];
 65         update(la,ra-1,1,sz,1,sc[i].f);
 66         ans+=abs(sum[1]-lst);
 67     }
 68     return ans;
 69 }
 70 int solvey()
 71 {
 72     int ans=0,lst=0;
 73     for(int i=1;i<=n;i++)
 74     {
 75         a[2*i-1]=q[i].b1,a[2*i]=q[i].b2;
 76         sc[2*i-1].l=q[i].b1,sc[2*i].l=q[i].b1;
 77         sc[2*i-1].r=q[i].b2,sc[2*i].r=q[i].b2;
 78         sc[2*i-1].h=q[i].a1,sc[2*i].h=q[i].a2;
 79         sc[2*i-1].f=1,sc[2*i].f=-1;
 80     }
 81     sort(a+1,a+2*n+1);
 82     sz=unique(a+1,a+2*n+1)-(a+1);
 83     sort(sc+1,sc+2*n+1,cmp1);
 84     for(int i=1;i<=2*n;i++)
 85     {
 86         int la=lower_bound(a+1,a+sz+1,sc[i].l)-a;
 87         int ra=lower_bound(a+1,a+sz+1,sc[i].r)-a;
 88         lst=sum[1];
 89         update(la,ra-1,1,sz,1,sc[i].f);
 90         ans+=abs(sum[1]-lst);
 91     }
 92     return ans;
 93 }
 94 
 95 int main()
 96 {
 97     //freopen("data.in","r",stdin);
 98     scanf("%d",&n);
 99     for(int i=1;i<=n;i++)
100         scanf("%d%d%d%d",&q[i].a1,&q[i].b1,&q[i].a2,&q[i].b2);
101     int ret=0;
102     ret+=solvex();
103     clr();
104     ret+=solvey();
105     printf("%d\n",ret);
106     return 0;
107 }

 

hdu1828 Picture (线段树:扫描线周长)

标签:void   扫描   algo   print   str   long   shu   using   答案   

原文地址:https://www.cnblogs.com/guapisolo/p/9697021.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!