• hdu1255 矩阵的交 线段树+扫描线


    /*
        不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,
        应该是,可以确定,这个区间被完全覆盖了1次,
        而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,
        只要加上t[lch].s + t[rch].s  即,看看左右孩子区间被覆盖了一次或以上的长度,
        那么叠加在双亲上就是双亲被覆盖两次或以上的长度
    */
    
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define maxn 1005
    struct segment
    {
        double l,r,h;
        int f;
    }s[maxn*2];
    struct node
    {
        int cnt;
        double len1;//记录一次及以上的
        double len2;//记录二次及以上的
    }tree[maxn*8];
    double mark[maxn<<1];
    bool cmp(segment a,segment b)
    {
        return a.h<b.h;
    }
    void build(int l,int r,int rt)
    {
        tree[rt].cnt=0;
        tree[rt].len1=tree[rt].len2=0;
        if(l==r)
        {    
            return ;
        }
        int m=(l+r)/2;
        build(lson);
        build(rson);
    }
    /*
        重点。 
        若该节点的cnt >= 2,说明被至少两条线段覆盖,那么len1=len2=区间长度。 
        若该节点的cnt == 1,说明该区间被一条线段覆盖,len1=区间长度,只要左右节点的len1有值, 
        那么那些长度一定是至少被覆盖两次的,因此len2为左右节点的len1之和。 
        若该节点的cnt = 0,说明没被完全覆盖,直接用其左右节点更新。 
        还要注意特判叶子节点。 
    */
    void getlen(int l,int r,int rt)
    {
        if(tree[rt].cnt>=2)//>=2时很好理解,就是覆盖2次或以上,直接减一减
        {
            tree[rt].len1=mark[r+1]-mark[l];
            tree[rt].len2=mark[r+1]-mark[l];
        }
        else if(tree[rt].cnt==1)//此处需要注意
                                //由于cnt大于0,所以覆盖一次或以上的部分直接得到,而由于完全覆盖一次
                                //可能其他部分有覆盖,此时就可以根据左右孩子来,由于len1记录覆盖一次或
                                //以上的,因为已经完全覆盖了一次,只要加上左右孩子的一次或以上覆盖的值
                                //那么就是2次或以上覆盖的值。
        {
            tree[rt].len1=mark[r+1]-mark[l];//因为覆盖一次,len1还要继续加
            if(l == r)//由于覆盖一次,又只有一个l==r,所以len2为0
            {
                tree[rt].len2=0;
            }
            else
            {
                tree[rt].len2=tree[rt<<1].len1+tree[rt<<1|1].len1;
            }
        }
        else if(tree[rt].cnt==0)//为完全覆盖,根据孩子来。此处与上面等于1出相似,可以发现,如果为完全覆盖
                                //就可以根据左右孩子得到覆盖的,那cnt等于1时,要求覆盖2次的时候就也可以
                                //根据孩子来。
        {
            if(l == r)
                tree[rt].len1=tree[rt].len2=0;
            else
            {
                tree[rt].len1=tree[rt<<1].len1+tree[rt<<1|1].len1;
                tree[rt].len2=tree[rt<<1].len2+tree[rt<<1|1].len2;
            }
        }
    }
    void updata(int L,int R,int c,int l,int r,int rt)
    {
        if(l>=L&&R>=r)
        {
            tree[rt].cnt+=c;
            getlen(l,r,rt);
            return ;
        }
        int m=(l+r)/2;
        if(m>=L)
            updata(L,R,c,lson);
        if(R>m)
            updata(L,R,c,rson);
        getlen(l,r,rt);
    }
    int find(double val,int x,int y)
    {
        int l=x,r=y,m;
        while(l<=r)
        {
            m=(l+r)/2;
            if(mark[m]==val)
                return m;
            else if(mark[m]>val)
                r=m-1;
            else l=m+1;
        }
        return -1;
    }
    int main()
    {
        int t,n,i;
        double x1,x2,y1,y2;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            int m=0;
            for(i=0;i<n;i++)
            {
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                s[m].l=x1;s[m].r=x2;s[m].h=y1;s[m].f=1;mark[m++]=x1;
                s[m].l=x1;s[m].r=x2;s[m].h=y2;s[m].f=-1;mark[m++]=x2;
            }
            sort(s,s+m,cmp);
            sort(mark,mark+m);
            int k=1;
            for(i=1;i<m;i++)
            {
                if(mark[i]!=mark[i-1])
                    mark[k++]=mark[i];
            }
            /*
            for(i=0;i<k;i++)
                printf("%.2lf ",mark[i]);
            printf("
    ");
            */
            build(0,k-1,1);
            double ans=0;
            for(i=0;i<m;i++)
            {
                int ll=find(s[i].l,0,k-1);
                int rr=find(s[i].r,0,k-1)-1;
                updata(ll,rr,s[i].f,0,k-1,1);
                ans+=(s[i+1].h-s[i].h)*tree[1].len2;
            }
            printf("%.2lf
    ",ans);
        }
    }
  • 相关阅读:
    Swift之类型安全和类型推断
    Swift之浮点数
    Swift之整数
    泛互联网产品技术支持划分
    WPF WebBrowser 不可见问题的解析[转]
    form WebBrowser自动点击弹出提示框alert、弹出对话框confirm、屏蔽弹出框、屏蔽弹出脚本错误的解决办法
    Mvvm绑定datagrid或listview的selectItems的方法[转]
    [C#]获取最近在Windows上所使用的文件
    拷贝构造函数和赋值运算符重载的区别
    Why Doesn’t Drag-and-Drop work when my Application is Running Elevated? – A: Mandatory Integrity Control and UIPI(转载)
  • 原文地址:https://www.cnblogs.com/sweat123/p/4656798.html
Copyright © 2020-2023  润新知