线段树扫描线 求矩阵的覆盖面积与周长

学习资料处

HDU 1542 Atlantis

题意:给出几个矩阵求这些矩阵覆盖的面积:

给出左上角与右下角

Sample Input

2
0 5 4 1
2 4 6 2

Sample Output

20

 

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define lson l, m, rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 5e3 + 10;
const int Base = 1e8;
LL sum[maxn<<2];
int add[maxn];
int x[maxn<<2];

struct Node{
    int flag;
    int l, r, h;
    Node(){};
    Node(int L, int R, int H, int F):l(L),r(R),h(H),flag(F){};
    bool operator < (const Node & rhs) const{
        return this->h < rhs.h;
    };
}s[maxn];
 void UPDOWN(int rt, int l, int r)
{
    if(add[rt]) sum[rt] = x[r+1] - x[l];

    else if(l == r) sum[rt] = 0;
    else sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
 void UPDATE(int L, int R, int c, int l, int r, int rt)
{
    int m;
    if(L <= l && r <= R){
        add[rt] += c;
        UPDOWN(rt, l, r);
        return ;
    }
    m = (l+r)>>1;
    if(L <= m) UPDATE(L, R, c, lson);
    if(R >  m) UPDATE(L, R, c, rson);
    UPDOWN(rt, l, r);
}

int main(void)
{
    int n;
    scanf("%d", &n);
    int x1, x2, y1, y2;
    int num = 0;
    for(int i=0; i<n; i++){
        scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
        x1 += Base, x2 += Base, y1 += Base, y2 += Base;
        x[num] = x1;
        s[num++] = Node(x1, x2, y1, 1);
        x[num] = x2;
        s[num++] = Node(x1, x2, y2, -1);

    }
    sort(x, x+num);
    sort(s, s+num);
    int idx = std::unique(x, x+num) - x;
    int L, R;
    long long ans = 0;
    for(int i=0; i<num-1; i++){
        L = lower_bound(x, x+idx, s[i].l) - x;
        R = lower_bound(x, x+idx, s[i].r) - x - 1;
        UPDATE(L,R,s[i].flag,0,idx-1,1);
        ans+=(sum[1]*(1LL*s[i+1].h-1LL*s[i].h));
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

给出左上角与右下角求矩阵的周长

 
 
#include<string.h>
#include<stdio.h>
#include<bits/stdc++.h>
#include<algorithm>
#define lson l, m, rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 5010;
const int MAX  = 10010;
int add[2*MAX*4];
int sum[2*MAX*4];
struct Node{
    int flag;
    int l, r, h;
    Node(){};
    Node(int L, int R, int H):l(L),r(R),h(H){};
    bool operator < (const Node &rhs) const{
        if(this->h==rhs.h) return this->flag > rhs.flag;
        else return this->h < rhs.h;
    };
}sx[maxn<<1],sy[maxn<<1];

inline void Build(int l, int r, int rt)
{
    add[rt] = sum[rt] = 0;
    if(l >= r) return ;
    int m = l+((r-l)>>1);
    Build(lson);
    Build(rson);
}

inline void pushup(int rt, int l, int r)
{
    if(add[rt] > 0)    sum[rt] = r - l + 1;
    else if(l==r)      sum[rt] = 0;
    else               sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

inline void update(int L, int R, int c, int l, int r, int rt)
{
    int m;
    if(L <= l && r <= R){
        add[rt] += c;
        pushup(rt, l, r);
        return ;
    }
    m = l + ((r-l)>>1);
    if(L <= m) update(L, R, c, lson);
    if(R  > m) update(L, R, c, rson);
    pushup(rt, l, r);
}

int Solve(int minx, int maxx, int miny, int maxy, int num)
{
    int ret = 0;
    int pre = 0;
    Build(minx, maxx-1, 1);
    for(int i=0; i<num; i++){
        update(sx[i].l, sx[i].r-1, sx[i].flag, minx, maxx-1, 1);
        ret += abs(sum[1] - pre);
        pre = sum[1];
    }
    //printf("%d\n", ret);
    Build(miny, maxy-1, 1);
    pre = 0;
    for(int i=0; i<num; i++){
        update(sy[i].l, sy[i].r-1, sy[i].flag, miny, maxy-1, 1);
        ret += abs(sum[1] - pre);
        pre = sum[1];
    }
    return ret;
}

int main(void)
{
    //freopen("data1.in", "w", stdin);
    int n;
    while(~scanf("%d", &n)){
        int maxx, maxy, minx, miny;
        maxx = maxy = -0x3f3f3f3f;
        minx = miny =  0x3f3f3f3f;
        int x1, y1, x2, y2;
        int num = 0;
        for(int i=0; i<n; i++){
            scanf("%d %d %d %d", &x1,&y1,&x2,&y2);
            miny = min(y1, miny);
            minx = min(x1, minx);
            maxy = max(y2, maxy);
            maxx = max(x2, maxx);
            sx[num].l = x1, sx[num].r = x2, sx[num].h = y1, sx[num].flag = 1;
            sx[num+1].l=x1, sx[num+1].r=x2, sx[num+1].h=y2, sx[num+1].flag=-1;

            sy[num].l = y1, sy[num].r = y2, sy[num].h = x1, sy[num].flag = 1;
            sy[num+1].l=y1, sy[num+1].r=y2, sy[num+1].h=x2, sy[num+1].flag=-1;

            num+=2;
        }
        sort(sx, sx+num);
        sort(sy, sy+num);
        printf("%d\n", Solve(minx, maxx, miny, maxy, num));
    }
    return 0;
}
View Code

 

给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

 解析

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1010
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)

double pos[2*N];
struct segment
{
    double l,r,h;
    int v;
}s[2*N];
struct node
{
    int l,r,cnt;
    double s,ss;
    int mid()
    { return (l+r)>>1; }
}t[2*N*4];
int n;

int cmp(struct segment p ,struct segment q)
{
    return p.h<q.h;
}

void build(int l ,int r ,int rt)
{
    t[rt].l=l; t[rt].r=r;
    t[rt].cnt=t[rt].s=t[rt].ss=0;
    if(l==r) return ;
    int mid=t[rt].mid();
    build(l,mid,lch(rt));
    build(mid+1,r,rch(rt));
}

int binarysearch(double key ,int low ,int high)
{
    while(low <= high)
    {
        int mid=(low+high)>>1;
        if(pos[mid] == key)
            return mid;
        else if(pos[mid] < key)
            low=mid+1;
        else
            high=mid-1;
    }
    return -1;
}

void cal(int rt)
{
    if(t[rt].cnt)
        t[rt].s = pos[t[rt].r+1] - pos[t[rt].l];
    else if(t[rt].l == t[rt].r)
        t[rt].s=0;
    else
        t[rt].s = t[lch(rt)].s + t[rch(rt)].s;
/**************************************************/
    if(t[rt].cnt > 1)
        t[rt].ss = pos[t[rt].r+1] - pos[t[rt].l];
    else if(t[rt].l == t[rt].r)
        t[rt].ss = 0;
    else if(t[rt].cnt == 1)
        t[rt].ss = t[lch(rt)].s + t[rch(rt)].s;
    else
        t[rt].ss = t[lch(rt)].ss + t[rch(rt)].ss;
}

void updata(int l , int r ,int v ,int rt)
{
    if(t[rt].l==l && t[rt].r==r)
    {
        t[rt].cnt += v;
        cal(rt);
        return ;
    }
    int mid=t[rt].mid();
    if(r<=mid)     updata(l,r,v,lch(rt));
    else if(l>mid) updata(l,r,v,rch(rt));
    else
    {
        updata(l,mid,v,lch(rt));
        updata(mid+1,r,v,rch(rt));
    }
    cal(rt);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int i,k;
        for(i=0,k=0; i<n; i++,k+=2)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            pos[k]=x1; pos[k+1]=x2;
            s[k].l=x1;   s[k].r=x2;   s[k].h=y1;   s[k].v=1;
            s[k+1].l=x1; s[k+1].r=x2; s[k+1].h=y2; s[k+1].v=-1;
        }
        sort(pos,pos+k);
        sort(s,s+k,cmp);
        int m=1;
        for(i=1; i<k; i++)
            if(pos[i]!=pos[i-1])
                pos[m++]=pos[i];

        build(0,m-1,1);
        double res=0;
        for(i=0; i<k-1; i++)
        {
            int l=binarysearch(s[i].l,0,m-1);
            int r=binarysearch(s[i].r,0,m-1)-1;
            updata(l,r,s[i].v,1);
            res += t[1].ss*(s[i+1].h - s[i].h);
        }
        printf("%.2lf\n",res);
    }
    return 0;
}
View Code

 

posted @ 2018-11-27 18:06  shuai_hui  阅读(369)  评论(0编辑  收藏  举报