zoukankan      html  css  js  c++  java
  • 扫描线+线段树例题(HDU1542)

    主要作为代码参考

    http://acm.hdu.edu.cn/showproblem.php?pid=1542


    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    const int M=2222;
    double X[M];//离散化
    struct node{
        double l,r,h;//因为有小数,所以我们存边的时候要存为小数
        int d;//存上边还是下边
    }nodes[M];
    struct t{//线段树 
        int cnt;//线段树存下边数-上边数,如果子节点下边数-上边数不同我们直接赋值-1
        double sum;//区间长度
    }tr[M*4];
    bool cmp(node a,node b){
        return a.h<b.h;
    }
    void pushup(int i){//上推 
        if(tr[i*2].cnt==-1||tr[i*2+1].cnt==-1){
            tr[i].cnt=-1;
        }else if (tr[i*2].cnt!=tr[i*2+1].cnt){
            tr[i].cnt=-1;
        }else
            tr[i].cnt=tr[i*2].cnt;
        tr[i].sum=tr[i*2].sum+tr[i*2+1].sum;
    }
    void pushdown(int i,int l,int r){
        int mid=(r+l)/2;
        if(tr[i].cnt!=-1){
            tr[i*2].cnt=tr[i*2+1].cnt=tr[i].cnt;
            if(tr[i].cnt==0){
                tr[i*2].sum=tr[i*2+1].sum=0;
            }else{
                tr[i*2].sum=X[mid+1]-X[l];
                tr[i*2+1].sum=X[r+1]-X[mid+1];
            }
        }
    }
    void build(int i,int l,int r){//建线段树 
        if(l==r){//叶子结点 
            tr[i].sum=0;
            tr[i].cnt=0;
            return;
        }
        int mid =(r+l)/2;
        build(i*2,l,mid);
        build(i*2+1,mid+1,r);
        pushup(i);
    }
    void update(int i,int l,int r,int x,int y,int d){
        if(x<=l&&y>=r){
            if(tr[i].cnt!=-1){
                tr[i].cnt+=d;
                tr[i].sum=(tr[i].cnt?(X[r+1]-X[l]):0);
                return;
            }
        }
        pushdown(i,l,r);
        int mid=(r+l)/2;
        if(x<=mid)
        update(i*2,l,mid,x,y,d);
        if(y>mid)
        update(i*2+1,mid+1,r,x,y,d);
        pushup(i);
    }
    int bin(double k,int n,double d[]){
        int l=1,r=n;
        while(l<=r){
            int mid=(r+l)/2;
            if(d[mid]<k){
                l=mid+1;
            }else if(d[mid]==k)
            	return mid;
            else{
                r=mid-1;
            }
        }
        return -1;
    }
    int main(){
        int q;
        int kase=0;
        while(~scanf("%d",&q)&&q){
            int n=0,m=0;
            for(int i=1;i<=q;i++){
                double x1,y1,x2,y2;
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                X[++n]=x1;//存边 
                nodes[++m].l=x1;
                nodes[m].r=x2;
                nodes[m].h=y1;
                nodes[m].d=1;
                X[++n]=x2;
                nodes[++m].l=x1;
                nodes[m].r=x2;
                nodes[m].h=y2;
                nodes[m].d=-1;
            }
            sort(X+1,X+1+n);
            sort(nodes+1,nodes+1+m,cmp);//排序 
            int k=1;
            for(int i=2;i<=n;i++){
                if(X[i-1]!=X[i])
                    X[++k]=X[i];//离散化 
            }
            build(1,1,k-1);//在x轴上一共有k-1段
            double ret=0.0;
            for(int i=1;i<m;i++){
                int x,y;
                x=bin(nodes[i].l,k,X);
                y=bin(nodes[i].r,k,X)-1;
                if(x<=y)
                update(1,1,k-1,x,y,nodes[i].d);
                ret+=tr[1].sum*(nodes[i+1].h-nodes[i].h);
            }
            printf("Test case #%d
    Total explored area: %.2lf
    
    ",++kase,ret);
        }
        return 0;
    }
  • 相关阅读:
    发送 GET 和 POST 请求
    日志记录帮助类
    常用正则表达式
    获取验证码
    C# 生成二维码
    android sql Cursor
    sql 语句操作
    android 界面悬浮框实现
    android activity四种启动模式
    andorid 自定义view属性declare-styleable
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680640.html
Copyright © 2011-2022 走看看