zoukankan      html  css  js  c++  java
  • HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并

    解法:跟求矩形面积并差不多,不过线段树节点记录的为:

    len: 此区间线段长度

    cover: 此区间是否被整个覆盖

    lmark,rmark: 此区间左右端点是否被覆盖

    num: 此区间分离开的线段的条数

    重点在转移的地方,不难理解。

    代码:

    #include <iostream>
    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define N 10007
    
    struct node
    {
        int cov,len,num,lmark,rmark;
    }tree[8*N];
    
    struct Line
    {
        int y1,y2,x;
        int cov;
    }line[2*N];
    int yy[2*N];
    
    int cmp(Line ka,Line kb)
    {
        return ka.x < kb.x;
    }
    
    int bsearch(int l,int r,int x)
    {
        while(l <= r)
        {
            int mid = (l+r)/2;
            if(x == yy[mid])
                return mid;
            if(x > yy[mid])
                l = mid+1;
            else
                r = mid-1;
        }
        return l;
    }
    
    void build(int l,int r,int rt)
    {
        tree[rt].cov = tree[rt].len = tree[rt].num = tree[rt].lmark = tree[rt].rmark = 0;
        if(l == r-1) return;
        int mid = (l+r)/2;
        build(l,mid,2*rt);
        build(mid,r,2*rt+1);
    }
    
    void pushup(int l,int r,int rt)
    {
        if(tree[rt].cov)
        {
            tree[rt].len = yy[r]-yy[l];
            tree[rt].lmark = tree[rt].rmark = 1;
            tree[rt].num = 1;
        }
        else if(l+1 == r)
            tree[rt].len = tree[rt].num = tree[rt].lmark = tree[rt].rmark = 0;
        else
        {
            tree[rt].len = tree[2*rt].len + tree[2*rt+1].len;
            tree[rt].lmark = tree[2*rt].lmark;
            tree[rt].rmark = tree[2*rt+1].rmark;
            tree[rt].num = tree[2*rt].num+tree[2*rt+1].num-tree[2*rt].rmark*tree[2*rt+1].lmark;
            //如果左右区间连续,那么可以合并,减少一个区间
        }
    }
    
    void update(int l,int r,int aa,int bb,int cover,int rt)
    {
        if(aa <= l && bb >= r)
        {
            tree[rt].cov += cover;
            pushup(l,r,rt);
            return;
        }
        if(l+1 == r) return;
        int mid = (l+r)/2;
        if(aa <= mid)
            update(l,mid,aa,bb,cover,2*rt);
        if(bb > mid)
            update(mid,r,aa,bb,cover,2*rt+1);
        pushup(l,r,rt);
    }
    
    int main()
    {
        int n,m,cs = 1,i,j;
        int x1,y1,x2,y2;
        while(scanf("%d",&n)!=EOF)
        {
            m = 1;
            for(i=0;i<n;i++)
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                line[m].x = x1,line[m].y1 = y1,line[m].y2 = y2,line[m].cov = 1,yy[m++] = y1;
                line[m].x = x2,line[m].y1 = y1,line[m].y2 = y2,line[m].cov = -1,yy[m++] = y2;
            }
            m--;
            sort(yy+1,yy+m+1);
            int cnt = 2;
            for(i=2;i<=m;i++)
            {
                if(yy[i] != yy[i-1])
                    yy[cnt++] = yy[i];
            }
            cnt--;
            build(1,cnt,1);
            sort(line+1,line+m+1,cmp);
            int ans = 0;
            int last = 0;
            for(i=1;i<=m;i++)
            {
                int L = bsearch(1,cnt,line[i].y1);
                int R = bsearch(1,cnt,line[i].y2);
                update(1,cnt,L,R,line[i].cov,1);
                ans += abs(last - tree[1].len);
                if(i == m) break;
                ans += tree[1].num*2*(line[i+1].x-line[i].x);
                last = tree[1].len;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    windows常规
    oracle常规操作
    idea使用
    java-maven
    java-rabbimq
    centos7 rabbitMq 安装教程
    Leetcode 332.重新安排行程
    Leetcode 334.递增的三元子序列
    Leetcode 331.验证二叉树的前序序列化
    Leetcode 330.按要求补齐数组
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3941163.html
Copyright © 2011-2022 走看看