zoukankan      html  css  js  c++  java
  • 讲课专用——线段树——矩形并的周长

    题目链接:http://poj.org/problem?id=1177

    N<=5000个矩形 坐标范围[-10000,10000] ,均为整数 求矩形并的周长

    对横着的和竖着的分别求一次
    暴力算法:
    对于每一条横边从左到右扫一遍,如果是矩形的下边,先判断当前坐标覆盖数为0,ans+,然后当前坐标覆盖数+1(覆盖数不为0也要加)
    如果是矩形的上边,先判断当前坐标覆盖数为1,ans++,然后当前坐标覆盖数-1(覆盖数不为1也要减)
    对于每一条竖边,同理(下边改成左边,上边改成右边)
    注:1、边[l,r]的扫描范围为[l,r-1]
    2、排序时,若几条横边的高度一样,上边优先。同理,竖边左边优先。
    原因:这种情况下是一个矩形的下边和另一个矩形的上边重合,两条边的长度都不能算。
    如果先扫下边,扫下边之前一定扫了上边,坐标覆盖可能为1,导致答案错误累加

    线段树做法:
    类似于求矩形并的面积
    不同点:累加答案累加与上一次的差,不需要再乘高度
    注:1、边[l,r]的扫描范围是[l,r-1]
    2、排序时,若几条边高度一样,谁在前无所谓。因为累加与上一次的差

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define delta 10001
    #define N 20002
    
    struct rectangle
    {
        int x,l,r,f;
    }tra[N],ver[N]; 
    
    int sum[N<<2],col[N<<2];
    int opl,opr,fl;
    
    void read(int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } 
        x*=f; 
    } 
    
    bool cmp1(rectangle a,rectangle b)
    {
        return a.x<b.x;
    }
    
    void up(int k,int l,int r)
    {
        if(col[k]) sum[k]=r-l+1;
        else if(l==r) {sum[k]=0; return;}
        else sum[k]=sum[k<<1]+sum[k<<1|1];
    }
    
    void change(int k,int l,int r)
    {
        if(l>=opl && r<=opr)
        {
            col[k]+=fl; 
            up(k,l,r);
            return;
        }
        int mid=l+r>>1;
        if(opl<=mid) change(k<<1,l,mid);
        if(opr>mid) change(k<<1|1,mid+1,r);
        up(k,l,r);
    }
    
    int main()
    {
        int n;
        read(n);
        int x1,y1,x2,y2;
        int a,b;
        for(int i=1;i<=n;++i)
        {
            read(x1); read(y1); read(x2); read(y2); 
            x1+=delta; y1+=delta; x2+=delta; y2+=delta;
            a=i*2-1; b=i*2;
            tra[a].l=y1; tra[a].r=y2; 
            tra[a].x=x1; tra[a].f=1;
            tra[b].l=y1; tra[b].r=y2; 
            tra[b].x=x2; tra[b].f=-1; 
            ver[a].l=x1; ver[a].r=x2; 
            ver[a].x=y1; ver[a].f=1;
            ver[b].l=x1; ver[b].r=x2;
            ver[b].x=y2; ver[b].f=-1;
        }
        int m=n<<1; 
        sort(tra+1,tra+m+1,cmp1);
        int ans=0,last=0;
        for(int i=1;i<=m;++i)
        {
            opl=tra[i].l; opr=tra[i].r-1; fl=tra[i].f;
            change(1,1,N-1);
            ans+=abs(sum[1]-last);
            last=sum[1];
        }
        sort(ver+1,ver+m+1,cmp1);
        last=0;
        for(int i=1;i<=m;++i)
        {
            opl=ver[i].l; opr=ver[i].r-1; fl=ver[i].f;
            change(1,1,N-1);
            ans+=abs(sum[1]-last);
            last=sum[1];
        }
        printf("%d",ans);
    }
  • 相关阅读:
    【原】cookie和session的区别
    【总结】资源汇总(二)
    【总结】资源汇总(一)
    【原】linux设置网络延迟/丢包操作
    【原】Web Polygraph 安装
    【原】openresty学习
    【原】nginx配置文件
    【原】postman常用设置全局变量的js片段
    application.yml配置文件没有出现小绿叶子
    The project com.myself.springcloud:cloud2021:1.0-SNAPSHOT (D:ideaOldProjectcloud2021pom.xml) has 1 error;idea Module '****' already exist in project. Please, specify another name.
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/11144151.html
Copyright © 2011-2022 走看看