zoukankan      html  css  js  c++  java
  • 线段树--P5490 【模板】扫描线

    应该是九月份最后一篇了,这段时间比较高产,国庆勉强能休2天,不用写国庆作业是我不敢想象的快乐(⊙v⊙),楼下书桌里卷子能有1.5cm,肉眼可见的知识的厚度

    回归正题,扫描线和正常线段树的差别就在于我维护的是什么,我怎么维护

    扫描线和它的名字一样,一条平行于x轴的直线,从下往上扫过n个矩形,划分成多个区域,如图:

    求矩形的面积,我们需要知道长和高,而线段长可以转化成坐标差,所以X数组可以用来记录坐标,举个栗子:

    我们还知道每次都一定是先经过一个矩形的下底再经过一个上底,所以把上底附为-1,下底附为1,记录一下高度,矩形的高就可以表示为上一个扫面线的高度减下一个扫描线的高度,线段树维护一下矩形的长和下底的长度就可以了,记得把X数组进行排序

    pushup函数:如果我碰到了一个下底,更新的矩形长为右坐标减左坐标,否则为左儿子的长加右儿子的长

    1 void pushup(int k,ll l,ll r){
    2   if (tree[k].sum){tree[k].len=x[r+1]-x[l];return;}
    3   tree[k].len=tree[ls(k)].len+tree[rs(k)].len;
    4 }

    update函数:如果是下底,那么sum就有了值,代表扫描线网上的地方需要计算面积,如果是上底,那么sum不一定没有值,只是减少,代表它对应的矩形面积计算完毕

    1 void update(int k,ll l,ll r,ll nl,ll nr,int val){
    2   if(x[r+1]<=nl||nr<=x[l]) return;
    3   if (nl<=x[l]&&x[r+1]<=nr){tree[k].sum+=val;pushup(k,l,r);return;}
    4   int mid=(l+r)>>1;
    5   update(ls(k),l,mid,nl,nr,val);
    6   update(rs(k),mid+1,r,nl,nr,val);
    7   pushup(k,l,r);
    8 }

    完整代码,感觉自己讲的不太好,但是代码写的应该还是挺清楚的:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #define ll long long
     6 #define ls(x) (x<<1)
     7 #define rs(x) (x<<1|1)
     8 using namespace std;
     9 const int maxn=4e5+10;
    10 ll n,xx1,xx2,yy1,yy2,ans;
    11 struct node{
    12   ll l,r,h;
    13   int val;
    14 }line[maxn*4];
    15 bool operator < (const node &x,const node &y){
    16   return x.h<y.h;
    17 }
    18 struct ask{
    19   int sum;
    20   ll len;
    21 }tree[maxn*4];
    22 ll x[2*maxn];
    23 void pushup(int k,ll l,ll r){
    24   if (tree[k].sum){tree[k].len=x[r+1]-x[l];return;}
    25   tree[k].len=tree[ls(k)].len+tree[rs(k)].len;
    26 }
    27 void update(int k,ll l,ll r,ll nl,ll nr,int val){
    28   if(x[r+1]<=nl||nr<=x[l]) return;
    29   if (nl<=x[l]&&x[r+1]<=nr){tree[k].sum+=val;pushup(k,l,r);return;}
    30   int mid=(l+r)>>1;
    31   update(ls(k),l,mid,nl,nr,val);
    32   update(rs(k),mid+1,r,nl,nr,val);
    33   pushup(k,l,r);
    34 }
    35 int main(){
    36     scanf ("%lld",&n);
    37     for(int i = 1;i <= n;i++){
    38       scanf("%lld%lld%lld%lld",&xx1,&yy1,&xx2,&yy2);
    39       x[2*i-1]=xx1,x[2*i]=xx2;
    40       line[2*i-1]=(node){xx1,xx2,yy1,1};
    41       line[2*i]=(node){xx1,xx2,yy2,-1};
    42     }
    43     n<<=1;
    44     sort(line+1,line+n+1);
    45     sort(x+1,x+n+1);
    46     int cnt=unique(x+1,x+n+1)-x-1;
    47     for (int i = 1;i < n;i++){
    48       update(1,1,cnt-1,line[i].l,line[i].r,line[i].val);
    49       ans+=tree[1].len*(line[i+1].h-line[i].h);
    50     }
    51     printf("%lld
    ",ans);
    52   return 0;
    53 }
  • 相关阅读:
    java之md5加密算法
    springboot之快速创建项目
    java之idea打jar包
    java只http改成https访问
    springboot之读取配置文件
    springboot之项目打包
    Git之fatal: remote origin already exists
    WebStorm ES6 语法支持设置和ES6语法的JS文件编译为ES5语法文件
    转 JavaScript里的数组转化新方法Array.From
    网页特殊符号HTML代码大全
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13752869.html
Copyright © 2011-2022 走看看