扫描线总结【线段树特殊性质,没有pushdown、query操作】

扫描线

题意

多个矩阵求交集,线段树的特殊操作,非常特殊的情况,一堆证明之后,就没有pushdown操作。

没有pushdown操作,也没有query操作,直接tr[1].len.

亚特兰蒂斯

由于点可能有小数,先l、离散化为整数,这里的线段树存的是一个区间:【L,R),左闭右开的区间。 换句话:线段树存的是第几个小区间,那么操作(l,r)的话,对线段树操作:l–r-1就够了,(存的不是点,是小区间,小区间比点的数量少1)

另外,也不需要query()函数,之间调用tr[1].len,返回线段长度

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;
struct seg1{
    double x,y1,y2;
    int k;
    bool operator<(const seg1 & t)const{
        return x<t.x;
    }
}seg[N];
struct node{
    int l,r,cnt;
    double len;
}tr[N];

vector<double>ys;
double find(double y)
{
    return lower_bound(ys.begin(),ys.end(),y) - ys.begin();
}

void build(int u,int l,int r)
{
    if(l==r) tr[u]={l,r,0,0.0};
    else{
        tr[u]={l,r,0,0.0};
        int mid=l+r>>1;
        build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    }
}
void pushup(int u)
{
    if(tr[u].cnt)
    {
        tr[u].len=(ys[tr[u].r+1]-ys[tr[u].l]);

    }
    else if(tr[u].l!=tr[u].r)
    {
        tr[u].len= tr[u<<1].len+tr[u<<1|1].len;
    }
    else tr[u].len=0;
}

void modify(int u,int l,int r,int k)
{
    if(tr[u].l>=l && tr[u].r<=r)
    {
        tr[u].cnt+=k;
        pushup(u);
    }
    else{
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid) modify(u<<1,l,r,k);
        if(r>mid) modify(u<<1|1,l,r,k);
        pushup(u);
    }
}
int main() {
    int T=1;
    while(cin>>n)
    {
        if(n==0) break;
        ys.clear();
        for(int i=0,j=0;i<n;i++)
        {
            double x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            
            ys.push_back(y1);
            ys.push_back(y2);
            seg[j++]={x1,y1,y2,1};
            seg[j++]={x2,y1,y2,-1};
        }
        sort(seg,seg+n*2);
        sort(ys.begin(),ys.end());
        ys.erase(unique(ys.begin(),ys.end()),ys.end());
        build(1,0,ys.size()-2);
        double res=0.0;
        for(int i=0;i<2*n;i++)
        {
            if(i>0) res+=(tr[1].len * (seg[i].x-seg[i-1].x));
            modify(1,find(seg[i].y1),find(seg[i].y2) -1 ,seg[i].k);
        }
        printf("Test case #%d\n", T ++ );
        printf("Total explored area: %.2lf\n\n", res);
    }   





    return 0;
}

普通版本扫描线

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;
struct seg1{
    int x,y1,y2;
    int k;
    bool operator<(const seg1 & t)const{
        return x<t.x;
    }
}seg[N];

struct node{
    int l,r,cnt;
    int len;
}tr[N];
void build(int u,int l,int r)
{
    if(l==r) tr[u]={l,r,0,0};
    else{
        tr[u]={l,r,0,0};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void pushup(int u)
{
    if(tr[u].cnt) tr[u].len = tr[u].r+1-tr[u].l;
    else if(tr[u].l!=tr[u].r) tr[u].len = tr[u<<1].len+tr[u<<1|1].len;
    else{
        tr[u].len=0;
    }
}
void motify(int u,int l,int r,int k)
{
    if(l<=tr[u].l && tr[u].r<=r) 
    {
        tr[u].cnt+=k;
        pushup(u);
    }
    else{
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid) motify(u<<1,l,r,k);
        if(r>mid)  motify(u<<1|1,l,r,k);
        pushup(u);
    }
}

int main() {
    cin>>n;
    int m = 0;
    for(int i=0,j=0;i<n;i++)
    {
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        seg[j++]={x1,y1,y2,1};
        seg[j++]={x2,y1,y2,-1};
    }
    //sort(seg, seg + m);
    sort(seg,seg+2*n);
    build(1,0,10000);
    
    ll res=0;
    for(int i=0;i<2*n;i++)
    {
        if(i>0) res+=tr[1].len * (seg[i].x - seg[i-1].x);
        motify(1,seg[i].y1,seg[i].y2-1,seg[i].k);

    }
    cout<<res<<endl;




    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值