2018-2019 Pacific Northwest Regional (Div. 1) F Rectangles(線段樹掃描線)

題目鏈接

題意: 矩形覆蓋面積奇數次的面積和

思路: 線段樹節點每次更新只用看其覆蓋奇數次還是偶數次,反轉一下即可!!節點的權值也要反轉,當前區間長度-上次區間權值 即爲節點反轉後的權值。仔細想一下即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson (rt<<1)
#define rson ((rt<<1)|1)
#define Mid ((L+R)>>1)
const int MAXN=201000;
struct pos
{
    int l,r;
    int h,f;
}p[MAXN];

struct node
{
    int lazy;
    int sum;    //邊的長度
}tree[MAXN<<2];
int x[MAXN];
int n;

bool cmp(pos a,pos b)
{
    return a.h < b.h;
}

void build(int rt,int L,int R)
{
    tree[rt].sum=0;
    tree[rt].lazy=0;
    if(L == R)  return ;
    build(lson,L,Mid);
    build(rson,Mid+1,R);
}

void pushup(int rt,int L,int R)
{
    tree[rt].sum=tree[lson].sum+tree[rson].sum;
    return ;
}

void pushdown(int rt,int L,int R)
{
    if(tree[rt].lazy){
        tree[lson].sum=x[Mid]-x[L-1]-tree[lson].sum;
        tree[rson].sum=x[R]-x[Mid]-tree[rson].sum;
        tree[lson].lazy^=1;
        tree[rson].lazy^=1;
        tree[rt].lazy=0;
        return ;
    }
}

void update(int rt,int L,int R,int l,int r,int v)
{
    if(l<=L&&R<=r){
        tree[rt].lazy^=1;
        tree[rt].sum=x[R]-x[L-1]-tree[rt].sum;  //每一個節點i的邊長都是x[i]-x[i-1]
        return ;
    }
    pushdown(rt,L,R);
    if(l<=Mid)   update(lson,L,Mid,l,r,v);
    if(Mid<r)   update(rson,Mid+1,R,l,r,v);
    pushup(rt,L,R);
}

int main()
{
    int tot=1;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int x1,x2,y1,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);//輸入一個矩形
        pos &t1 = p[tot];pos &t2 = p[1+tot];
        t1.l = t2.l = x1,t1.r = t2.r = x2;
        t1.h = y1;t1.f = 1;
        t2.h = y2;t2.f = -1;
        x[tot] = x1;x[tot+1] = x2;
        tot += 2;
    }
    sort(p+1,p+tot,cmp);//邊按高度從小到大排序(自下而上掃描)
    sort(x+1,x+tot);

    int k = 1;
    for (int i = 2;i < tot;++i)
        if (x[i] != x[i-1]) x[++k] = x[i];//去重
    build(1,1,k);
    ll ans=0;
    for(int i=1;i<tot-1;i++){
        int l = lower_bound(x+1,x+k,p[i].l) - x;//在橫座標數組裏找到這條邊的位置
        int r = lower_bound(x+1,x+k,p[i].r) - x ;
        update(1,1,k,l+1,r,p[i].f); //l+1是將邊的長度轉換爲節點的形式!!
        ans+=1ll*tree[1].sum*(p[i+1].h-p[i].h);
    }
    printf("%lld\n",ans);
    return 0;
}

發佈了48 篇原創文章 · 獲贊 2 · 訪問量 3035
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章