610D - Vika and Segments(线段树+扫描线+离散化)

扫描线:http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html

看图,图中的数字是横坐标离散后对应的下标,计算时左端点不变,右端点加1,所以总的更新的区间是l到r-1。

也可以理解为1代表的是(1到2这一段),2代表的是(2到3这一段),3代表的是(3到4这一段)。。。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ls rt<<1,l,m
#define rs rt<<1|1,m+1,r
#define mem(a,b) memset(a,b,sizeof(a))

const int N=1e5+5;
struct line
{
    int x1,x2;
    int h;
    int cover;
    bool operator < (const line &t)
    {
        return h<t.h;
    }
};
vector<line>l;
vector<int>w;
struct Tree
{
    int l,r;
    int sum;
    int cover;
}tree[N*8];

void push_up(int rt)
{
    if(tree[rt].cover)
    {
        tree[rt].sum=w[tree[rt].r+1]-w[tree[rt].l];
    }
    else
    {
        if(tree[rt].l==tree[rt].r)tree[rt].sum=0;
        else tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
    }
}

void build(int rt,int l,int r)
{
    tree[rt].sum=tree[rt].cover=0;
    tree[rt].l=l,tree[rt].r=r;
    if(l==r)return ;
    int m=(l+r)>>1;
    build(ls);
    build(rs);
}

void Update(int L,int R,int delta,int rt,int l,int r)
{
    if(L<=l&&r<=R)
    {
        tree[rt].cover+=delta;
        push_up(rt);
        return ;
    }
    int m=(l+r)>>1;
    if(L<=m)Update(L,R,delta,ls);
    if(R>m)Update(L,R,delta,rs);
    push_up(rt);
}

int binasrh(int val,int l,int r)
{
    int m;
    while(l<=r)
    {
         m=(l+r)>>1;
         if(w[m]==val)return m;
         else if(w[m]<val)l=m+1;
         else r=m-1;
    }
    return -1;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,x1,x2,y1,y2;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>x1>>y1>>x2>>y2;
        if(x1>x2||y1>y2)
        {
            swap(x1,x2);
            swap(y1,y2);
        }
        x2++;
        y2++;
        l.pb(line{x1,x2,y1,1});
        l.pb(line{x1,x2,y2,-1});
        w.pb(x1);
        w.pb(x2);
    }
    sort(w.begin(),w.end());
    sort(l.begin(),l.end());
    w.erase(unique(w.begin(),w.end()),w.end());

    ll ans=0;
    build(1,0,w.size()-1);
    for(int i=0;i<l.size()-1;i++)
    {
        int L=binasrh(l[i].x1,0,w.size()-1);
        int R=binasrh(l[i].x2,0,w.size()-1);
        if(L<R)Update(L,R-1,l[i].cover,1,0,w.size()-1);
        ans+=(ll)tree[1].sum*(l[i+1].h-l[i].h);
    }

    cout<<ans<<endl;
    return 0;
} 
时间: 2024-10-08 13:33:22

610D - Vika and Segments(线段树+扫描线+离散化)的相关文章

Codeforces 610D Vika and Segments 线段树+离散化+扫描线

可以转变成上一题(hdu1542)的形式,把每条线段变成宽为1的矩形,求矩形面积并 要注意的就是转化为右下角的点需要x+1,y-1,画一条线就能看出来了 #include<bits/stdc++.h> #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #pragma comment(linker,

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <

hdu1542 Atlantis (线段树+扫描线+离散化)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9032    Accepted Submission(s): 3873 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并

D. Vika and Segments Vika has an infinite sheet of squared paper. Initially all squares are white. She introduced a two-dimensional coordinate system on this sheet and drew n black horizontal and vertical segments parallel to the coordinate axes. All

HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8998    Accepted Submission(s): 3856 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <algor

HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11551    Accepted Submission(s): 4906 Problem Description There are several ancient Greek texts that contain descriptions of the fabled

杭电 HDU ACM 1225 Atlantis (线段树 扫描线 离散化 最基本)

acm第一发扫描线问题,其实算法原理很好理解 ,但是具体实现起来还是遇到诸多问题,我尝试参考了网上两份对于解决 线段树表示区间问题的方法, 第一种是每个结点的真实值,比如对于更新离散化后的1 ~ 4区间,我们在线段树中更新的是1 ~ 3,这样单个结点也可以表示一个最小单位区间. 第二种那就是在建树的时候改变通常策略,1 ~ 10 为总区间,两个孩子为1 ~ 5 ,5 ~ 10. 核心难点:当我们每次找到需要更新的区间,首先应该更新cover值,然后判断此时是被覆盖了,还是解除覆盖了,如果刚好被覆

hdu 5091 Beam Cannon(线段树+扫描线+离散化)

Beam Cannon Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 457    Accepted Submission(s): 175 Problem Description Recently, the γ galaxies broke out Star Wars. Each planet is warring for resou