• HDU


      这道题最开始我以为和HDU - 1542那道题一样,只需要把cover次数改成2次即可,但是后面仔细一想,我们需要求的是覆盖次数大于等于2次的,这样的话,我们需要维护两个长度,HDU-1542 由于求的是覆盖次数大于等于一次的,我们只需要维护一个覆盖次数大于等于1的长度的len1就行,但是这道题我们要求的是覆盖两次以及两次以上的长度,这样乘以高度差,才是面积。

    现在我们来想如何维护这个值?

    给线段树打个标记cover,代表这个区间被完全覆盖的次数。

    我们先来看看,维护覆盖一次及其以上的,应该怎么实现,我们可以从中得到启示。

    1. cover不为0 那么这个区间被完全覆盖。我们把整个区间长度给len1,但是我们由于经过离散化。表达式为:tree[root].len1=pos[r+1]-pos[l]
    2. L==R 代表跑到了叶子节点,不会有节点信息往上传,因此赋0
    3. 不满足上述两者,我们就可以认为,父节点的信息,又两个儿子节点的提供。

    那么覆盖两次的呢?同样的分情况讨论

    1. cover>1 那么这个区间内被完全覆盖至少2次,值等于区间长度。
    2. L==R 同样的信息不能由子节点提供,赋0
    3. Cover==1 那么这个区间被完全覆盖至少一,子节点覆盖次数大于等于1的次数往上pushup后,变成至少两次。
    4. 反之节点信息由两个子节点提供 
    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    inline int L(int r)
    {
        return r<<1;
    };
    inline int R(int r)
    {
        return r<<1|1;
    };
    inline int MID(int l,int r)
    {
        return (l+r)>>1;
    };
    const int maxx = 2015;
    struct Line
    {
        double l,r,h;
        int f;
    }line[maxx*2];
    struct node
    {
        int l,r,cover;
        double len1,len2;
    } tree[maxx<<2];
    double pos[maxx];
    bool cmp(Line a,Line b){
      return a.h<b.h;
    }
    void buildtree(int root,int l,int r)//建树
    {
        tree[root].l=l;
        tree[root].r=r;
        tree[root].len1=0;
        tree[root].len2=0;
        tree[root].cover=0;
        if (l==r)
        {
            return;
        }
        int mid = MID(l,r);
        buildtree(L(root),l,mid);
        buildtree(R(root),mid+1,r);
    }
    int bin(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 pushup(int root)
    {
        int l=tree[root].l;
        int r=tree[root].r;
        if (tree[root].cover)tree[root].len1=pos[r+1]-pos[l];
        else if (l==r)tree[root].len1=0;
        else tree[root].len1=tree[L(root)].len1+tree[R(root)].len1;
    
        if (tree[root].cover>1)tree[root].len2=tree[root].len1;
        else if (l==r)tree[root].len2=0;
        else if (tree[root].cover==1)tree[root].len2=tree[L(root)].len1+tree[R(root)].len1;
        else tree[root].len2=tree[L(root)].len2+tree[R(root)].len2;
    }
    void update(int root,int ul,int ur,int c)
    {
        int l=tree[root].l;
        int r=tree[root].r;
        if (ul<=l && r<=ur)
        {
            tree[root].cover+=c;
            pushup(root);
            return;
        }
        int mid=MID(l,r);
        if (ur<=mid)update(L(root),ul,ur,c);
        else if (ul>mid)update(R(root),ul,ur,c);
        else {
            update(L(root),ul,mid,c);
            update(R(root),mid+1,ur,c);
        }
        pushup(root);
    }
    int main()
    {
       int t;
       scanf("%d",&t);
       int n;
       while(t--){
         int nums=0;
         scanf("%d",&n);
         for (int i=0;i<n;i++){
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[nums].l=x1;
            line[nums].r=x2;
            line[nums].h=y1;
            line[nums].f=1;
            pos[nums++]=x1;
            line[nums].l=x1;
            line[nums].r=x2;
            line[nums].h=y2;
            line[nums].f=-1;
            pos[nums++]=x2;
         }
         sort(pos,pos+nums);
         sort(line,line+nums,cmp);
         int m=1;
         for (int i=1;i<nums;i++)//去重
            if (pos[i]!=pos[i-1])
            pos[m++]=pos[i];
         buildtree(1,0,m-1);
         double ans=0;
         for (int i=0;i<nums;i++)
         {
             int l=bin(line[i].l,0,m-1);
             int r=bin(line[i].r,0,m-1)-1;
             update(1,l,r,line[i].f);
             ans+=tree[1].len2*(line[i+1].h-line[i].h);
         }
         printf("%.2lf
    ",ans);
       }
       return 0;
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    JMX示例
    在开发iOS程序时对日期处理的总结(转)
    iOS 身份证验证(转)
    IOS --- OC与Swift混编(转)
    Charles辅助调试接口(转)
    iOS 调试 crash breakpoint EXC_BAD_ACCESS SIGABRT(转)
    Objective-C中常量重复定义的解决方案
    layoutSubviews、drawRect、initialize和load方法的调用
    (转)iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)
    Mac OS10.10 openfire无法启动问题(转)
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/10359046.html
Copyright © 2020-2023  润新知