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
  • 相关阅读:
    json转换成对象
    查看本机电脑的dns
    springboot整合jsp
    mysql DATE_FORMAT()函数用法
    checkbox全选反选
    mysql 中GROUP_CONCAT使用
    checkeds 选中获取tbale表格中某一列td标签中的值
    工具方法整理
    java开发微信公众号支付(JSAPI)
    Could not create connection to database server. Attempted reconnect 3 times. Giving up.错误
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10028062.html
Copyright © 2011-2022 走看看