蓝桥杯国赛奇偶覆盖

Posted iuk11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯国赛奇偶覆盖相关的知识,希望对你有一定的参考价值。

标准的二维扫描线模板题目。
在普通扫描线的基础上,要用离散化+线段树去优化。

普通扫描线

391数飞机
在一个数轴上扫描区间,可以规避掉:判断每一个点被多少个区间覆盖。
我们可以直接判断左右边界,有时左右边界集会间隔很大,为了建立线段树方便,或者为了减少访问次数,要先对数据集进行离散化。
对边界集进行排序,一段边界:左边界加一个权值1,右边界加一个权值-1。排序过后,用cnt记录从小到大的边界点的权值和,动态维护一个最大值,该值就是被最多区间覆盖的区域的覆盖区间个数。

离散化

对每一个分散的点进行编号,排序,这样在找一个点的真实值的时候,可以用二分去找到它的下标。

线段树

完成区间更新,区间查询的任务。

离散化+线段树的二维扫描线

洛谷P5490 [二维扫描线模板]
蓝桥杯 奇偶覆盖 [稍微变形]
【题目】给定n个矩形,每个矩形给左下角,右上角坐标。问被奇数个、偶数个矩形覆盖的总面积。
首先先确定一点:我们确定先对横坐标做一次扫描线的初始化,离散化。
当离散化完成,就可以便利的完成线段树的建树。因为这样的话区间都是可以一分为二的。
定义扫描线的结构体,包含:左端点、右端点、当前高度、是下边界or上边界(1 or -1)。
进行离散化,对X[]数组排序;对结构体按照高度由低到高排序。
tot本质不同的左右端点个数。
建树(可以不建,初始化而已,反正本来就都是0)
按照高度,开始遍历结构体,更新线段树。每一次都找到左右端点的位置,矩形线的范围;同时代入[1,tot],需要更新的范围;根节点1;当前范围的状态,下界or上界。
更新完成后维护一下面积和。区间长度乘以高度差
线段树更新细节:
两部分:pushup,向上更新,也就是我递归到最小[l,r]范围后,得到确定结果,然后再回溯到父节点更新,一直更新到根节点;update,更新操作,去卡范围。

#include<bits/stdc++.h>
using namespace std;
#define lson (x<<1)
#define rson (x<<1|1)
typedef long long ll;
const int N=7e5+100;
int n,cnt;
ll xx1,xx2,yy1,yy2,X[N<<1];
struct scanline
    ll l,r,h;
    int mark;
    bool operator < (const scanline &rhs) const 
        return h<rhs.h;
    
line[N<<1];
struct segtree
    int l,r,sum;
    ll len1,len2;//1 ji 2 ou
tree[N<<1];
void build(int x,int l,int r)
    tree[x].l=l,tree[x].r=r;
    tree[x].len1=0;
    tree[x].len2=0;
    tree[x].sum=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    return ;

void pushup(int x,int l,int r)
    if(tree[x].sum)
        if(tree[x].sum&1)
            tree[x].len2=tree[lson].len1+tree[rson].len1;//注意坑点 奇+奇=偶
            tree[x].len1=(X[r+1]-X[l])-tree[x].len2;
        else
            tree[x].len1=tree[lson].len1+tree[rson].len1;
            tree[x].len2=(X[r+1]-X[l])-tree[x].len1;
        
    else
        tree[x].len1=tree[lson].len1+tree[rson].len1;
        tree[x].len2=tree[lson].len2+tree[rson].len2;//与上面不同,仅统计个数
    

void update(int L,int R,int c,int l,int r,int x)
    if(L<=l&&R>=r)
        tree[x].sum+=c;
        pushup(x,l,r);
        return ;
    
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,c,l,mid,lson);
    if(R>mid) update(L,R,c,mid+1,r,rson);
    pushup(x,l,r);

int get(int x,int tot)
    return lower_bound(X+1,X+tot+1,x)-X;

int main()
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>xx1>>yy1>>xx2>>yy2;
        X[2*i-1]=xx1,X[2*i]=xx2;
        line[2*i-1]=(scanline)xx1,xx2,yy1,1;
        line[2*i]=(scanline)xx1,xx2,yy2,-1;
    
    n<<=1;
    sort(line+1,line+n+1);
    sort(X+1,X+n+1);
    int tot=unique(X+1,X+n+1)-X-1;
    build(1,1,tot-1);
    ll ans1=0,ans2=0;
    for(int i=1;i<n;i++)
        update(get(line[i].l,tot),get(line[i].r,tot)-1,line[i].mark,1,tot,1);
        ans1+=tree[1].len1*(line[i+1].h-line[i].h);
        ans2+=tree[1].len2*(line[i+1].h-line[i].h);
    
    cout<<ans1<<endl;
    cout<<ans2<<endl;
    return 0;

以上是关于蓝桥杯国赛奇偶覆盖的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯国赛奇偶覆盖

蓝桥杯国赛真题08python约分 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题08python约分 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题05python读数系统 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题04python输出平方 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题19Scratch青蛙王子 青少年组 scratch蓝桥杯国赛真题和答案讲解