zoukankan      html  css  js  c++  java
  • 覆盖的面积(扫描线求面积交

    # 题意

    多组测试样例,n表示矩形的个数,每个矩形用左上角和右下角来描述,输出这些矩形的面积交。

    # 题解

    同面积并思想一样,额外维护一个len2,表示覆盖线段大于2的长度

    分为两种情况

    1)当前的区间覆盖的线段个数大于2

    2)当前区间覆盖次数为1,加上子区间覆盖的1次的线段长度即当前覆盖大于2的总共长度

    3)覆盖次数为0,子区间可能存在,累加子区间的覆盖次数大于2的即可

     1 #include <bits/stdc++.h>
     2 #define pb push_back
     3 #define db double
     4 using namespace std;
     5 const int N = 100010;
     6 int n;
     7 struct Segment
     8 {
     9     double x, y1, y2;
    10     int k;
    11     bool operator< (const Segment &t)const
    12     {
    13         return x < t.x;
    14     }
    15 }seg[N * 2];
    16 struct Node
    17 {
    18     int l, r;
    19     int cnt;
    20     double len;
    21     double len2;
    22 }tr[N * 8];
    23 
    24 vector<double> ys;
    25 int find(db y){
    26     return lower_bound(ys.begin(),ys.end(),y)-ys.begin();
    27 }
    28 inline void push_up(int u)
    29 {
    30     if (tr[u].cnt) tr[u].len = ys[tr[u].r + 1] - ys[tr[u].l];//当前区间有覆盖,加上当前区间代表线段的长度
    31     else if (tr[u].l != tr[u].r)
    32     {
    33         tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len;//将当前的总长度传递到根节点
    34     }
    35     else tr[u].len = 0;
    36 
    37     if(tr[u].cnt>1) tr[u].len2=ys[tr[u].r + 1] - ys[tr[u].l];//区间多次覆盖
    38     else if(tr[u].l==tr[u].r) tr[u].len2=0;
    39     else if(tr[u].cnt==1) tr[u].len2=tr[u<<1].len+tr[u<<1|1].len;
    40     else tr[u].len2=tr[u<<1].len2+tr[u<<1|1].len2;
    41 }
    42 inline void build(int u, int l, int r)
    43 {
    44     tr[u] = {l, r, 0, 0,0};
    45     if (l != r)
    46     {
    47         int mid = l + r >> 1;
    48         build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    49     }
    50 }
    51 void change(int u,int l,int r,int k){
    52     if(tr[u].l >= l && tr[u].r <= r){
    53         tr[u].cnt += k;
    54         push_up(u);
    55     }
    56     else {
    57         int mid = tr[u].l + tr[u].r >> 1;
    58         if( l <= mid ) change(u<<1,l,r,k);
    59         if(r>mid) change(u<<1|1,l,r,k);
    60         push_up(u);
    61     }
    62 }
    63 int main(){
    64     int t;
    65     scanf("%d",&t);
    66     while(t--){
    67         scanf("%d",&n);
    68         ys.clear();
    69         for(int i=0,j=0;i<n;i++){
    70             double x1,y1,x2,y2;
    71             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    72             ys.pb(y1);
    73             ys.pb(y2);
    74             seg[j++]={x1,y1,y2,1};
    75             seg[j++]={x2,y1,y2,-1};
    76         }
    77         sort(ys.begin(),ys.end());
    78         ys.erase(unique(ys.begin(),ys.end()),ys.end());
    79         sort(seg,seg+2*n);
    80         build(1,0,ys.size()-2);//线段个数比点的个数少1
    81 
    82         db res=0;
    83         for(int i=0;i<n*2;i++){
    84             if(i > 0) res += tr[1].len2*(seg[i].x-seg[i-1].x);
    85             change(1,find(seg[i].y1),find(seg[i].y2)-1,seg[i].k);
    86         }
    87         printf("%.2lf
    ", res);
    88     }
    89 }
  • 相关阅读:
    AccessTokenValidation3 源码分析 jwttoken验证流程图
    .net core dump分析
    9102年了,汇总下HttpClient问题,封印一个
    Asp.net 性能监控之压测接口“卡住” 分析
    IdentityServer4源码颁发token分析及性能优化
    博客园设置看板娘和看板猫
    C# winform websocket学习笔记(三)HTML客户端
    C# winform websocket学习笔记(三)winform客户端
    C# winform websocket学习笔记(二)winform服务端
    C# winform websocket学习笔记(一)准备
  • 原文地址:https://www.cnblogs.com/hhyx/p/12514780.html
Copyright © 2011-2022 走看看