zoukankan      html  css  js  c++  java
  • 线段树扫描线 求矩阵的覆盖面积与周长

    学习资料处

    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
    ", 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
    ", 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
    ", 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
    ",res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10028062.html
Copyright © 2011-2022 走看看