luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树

Code:

#include<bits/stdc++.h>
#define maxn 200007
#define inf 100005
using namespace std;
void setIO(string s)
{
    string in=s+".in";
    freopen(in.c_str(),"r",stdin);
}
struct Edge
{
    int l,r,h,flag;
}edges[maxn];
int n;
namespace tr
{
    #define ls lson[o]
    #define rs rson[o]
    #define mid ((l+r)>>1)
    int tot;
    int lson[maxn<<2],rson[maxn<<2],lflag[maxn<<2],rflag[maxn<<2],sumv[maxn<<2],numv[maxn<<2],len[maxn<<2];
    int newnode() { return ++tot; }
    void pushup(int o,int l,int r)
    {
        if(sumv[o])
        {
            numv[o]=1;
            len[o]=r-l+1;
            lflag[o]=rflag[o]=1;
        }
        else
        {
            len[o]=len[ls]+len[rs];
            numv[o]=numv[ls]+numv[rs];
            if(rflag[ls]&&lflag[rs]) --numv[o];
            lflag[o]=lflag[ls];
            rflag[o]=rflag[rs];
        }
    }
    void add(int &o,int l,int r,int L,int R,int v)
    {
        if(!o) o=newnode();
        if(l>=L&&r<=R)
        {
            sumv[o]+=v;
            pushup(o,l,r);
            return;
        }
        if(L<=mid) add(ls,l,mid,L,R,v);
        if(R>mid) add(rs,mid+1,r,L,R,v);
        pushup(o,l,r);
    }
};
bool cmp(Edge a,Edge b)
{
    if(a.h==b.h)  return a.flag > b.flag;
    else  return a.h < b.h;
}
int main()
{
    //  setIO("input");
    scanf("%d",&n);
    int a,b,c,d,i,ed=0,j,root=0,last=0,ans=0;
    for(i=1;i<=n;++i)
    {
        scanf("%d%d%d%d",&a,&b,&c,&d);
        edges[++ed].l=a,edges[ed].r=c-1,edges[ed].h=b,edges[ed].flag=1;         // 加边
        edges[++ed].l=a,edges[ed].r=c-1,edges[ed].h=d,edges[ed].flag=-1;        // 删边
    }
    sort(edges+1,edges+1+ed,cmp);
    for(i=1;i<=ed;++i)
    {
        tr::add(root,-inf,inf,edges[i].l,edges[i].r,edges[i].flag);
        ans+=abs(tr::len[root]-last);
        last=tr::len[root];
        ans+=((tr::numv[root]<<1)*(edges[i+1].h-edges[i].h));
    }
    printf("%d\n",ans);
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/11049852.html

时间: 2024-10-09 06:17:59

luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树的相关文章

USACO5.5 矩形周长 Picture | 扫描线 + 线段树

题目:Luogu 1856 扫描线,将矩形拆成两条边分别为 +1 和 -1,计算无重叠部分的长度. 由于 update 区间 [a, b] 和 [b, c] 时会把 b 加两次,所以统一转换成 [a,b),累加长度的时候再将右端点右移. 需要注意,在覆盖一条边时,不能直接累加边的长度,像下图: 在覆盖边 [1,4] 前,[3,4] 已经累加过了,所以此时应该累计的是 [1,4] 的长度减去已经覆盖过的长度,然后再把 [1,4] 覆盖上: 相应的,在删除 [1,4] 这条边时,累计的是删除 [1,

[USACO5.5]矩形周长Picture[扫描线+线段树]

题意:给出一些矩阵,求这些矩阵合并后外部(被包括在内部的不算)周长 端点-1这个是用点代替了边,区间内有几个点就代表区间长度是多少 #include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; inline void chmax(int &x, int y) {if (x < y) x = y;} inline void chmin(int &x, int y) {if (x >

[线段树扫描线][USACO5.5]矩形周长Picture

墙上贴着许多形状相同的海报.照片.它们的边都是水平和垂直的.每个矩形图片可能部分或全部的覆盖了其他图片.所有矩形合并后的边长称为周长. 所有矩形的边界.所有矩形顶点的坐标都是整数. 输入文件的第一行是一个整数N(0<=N<5000),表示有多少个矩形.接下来N行给出了每一个矩形左下角坐标和右上角坐标(所有坐标的数值范围都在-10000到10000之间). 输出文件只有一个正整数,表示所有矩形的周长. 题解 线段树扫描线  https://www.luogu.org/problemnew/sol

[USACO5.5] 矩形周长Picture

https://www.luogu.org/problemnew/show/P1856 1.每个矩形由两条横向边和两条纵向边组成. 2.对于横向边,按纵坐标排序.设当前讨论的边为 A [s , t] 如果 A 是某个矩形的靠下的边,在树中查询[s,t]区间中被覆盖的长度为x,那么加上这条边后将增加(t-s-x); 如果 A 是某个矩形的靠上的边,先删除它的对应边,再在树中查询[s,t]区间中被覆盖的长度为x,那么加上这条边后将增加(t-s-x); 3.对于纵向边,按横坐标排序,讨论方法与横向边相

hdu1828 (Picture) &amp;poj 1177( Picture)&amp;sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)

题目地址:hdu1828 (Picture)  & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长) 题目大意: 给你N个矩形,求出N个矩形构成的周长. 解题思路: 线段数+扫描线. 推荐博客: POJ1177 Picture(线段树求轮廓周长) POJ 1177 Picture (线段树+离散化+扫描线) 详解 注意事项: 该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩

POJ1151Atlantis 矩形面积并 扫描线 线段树

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1151 题意概括 给出n个矩形,求他们的面积并. n<=100 题解 数据范围极小. 我们分3种算法逐步优化. 算法1: O(n3) 如果这n个矩形的坐标都是整数,而且比较小,那么我们显然可以用最暴力的方法:一个一个打标记. 但是不是这样的. 坐标大小很大,而且是实数. 然而我们发现差不多,只要先离散化一下,然后再打标记即可. 算法2:O(n2) 实际上,上面的方法十分慢.如果n的范围到了1000,

poj-1177 Picture(矩形周长并,线段树+扫描线)

题目链接:点击打开链接 Picture Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 11706   Accepted: 6175 Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical o

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> #include <algorithm> #define MAXN 110 #define LL ((rt<<1)+1) #define RR ((rt<<1)+2) using namespace std; int n; struct segment{ double l

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re