zoukankan      html  css  js  c++  java
  • hdu-5862 Counting Intersections(线段树+扫描线)

    题目链接:

    Counting Intersections

    Time Limit: 12000/6000 MS (Java/Others)  

      Memory Limit: 65536/65536 K (Java/Others)


    Problem Description
    Given some segments which are paralleled to the coordinate axis. You need to count the number of their intersection.

    The input data guarantee that no two segments share the same endpoint, no covered segments, and no segments with length 0.
     
    Input
    The first line contains an integer T, indicates the number of test case.

    The first line of each test case contains a number n(1<=n<=100000), the number of segments. Next n lines, each with for integers, x1, y1, x2, y2, means the two endpoints of a segment. The absolute value of the coordinate is no larger than 1e9.
     
    Output
    For each test case, output one line, the number of intersection.
     
    Sample Input
    2
    4
    1 0 1 3
    2 0 2 3
    0 1 3 1
    0 2 3 2
    4
    0 0 2 0
    3 0 3 2
    3 3 1 3
    0 3 0 2
     
    Sample Output
    4
    0
    题意:
     
    求这些与坐标轴平行的线段的交点有多少个;
     
    思路:
     
    差不多就是原来的一道CF的原题,传送门
    交点的个数就是每个线段覆盖的点数的和减去所有线段覆盖的点,而所有的线段覆盖的点数就可以用扫描线算法变成求面积;
     
    AC代码:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+4;
    int n,x1,x2,y3,y2,rec[2*N],num;
    struct no
    {
        int l,r,h,flag;
    };
    no line[8*N];
    struct nod
    {
        int l,r,cover;
        ll sum;
    };
    nod tree[8*N];
    int cmp(no x,no y)
    {
        return x.h<y.h;
    }
    void build(int node,int L,int R)
    {
        tree[node].l=L,tree[node].r=R;
        tree[node].cover=tree[node].sum=0;
        if(L>=R)return ;
        int mid=(L+R)>>1;
        build(2*node,L,mid);
        build(2*node+1,mid+1,R);
    }
    void Pushup(int node)
    {
        if(tree[node].cover)
        {
            tree[node].sum=rec[tree[node].r+1]-rec[tree[node].l];
        }
        else
        {
            if(tree[node].l==tree[node].r)tree[node].sum=0;
            else tree[node].sum=tree[2*node].sum+tree[2*node+1].sum;
        }
    }
    void update(int node,int L,int R,int x)
    {
        if(L<=tree[node].l&&R>=tree[node].r)
        {
            tree[node].cover+=x;
            Pushup(node);
            return ;
        }
        int mid=(tree[node].l+tree[node].r)>>1;
        if(L>mid) update(2*node+1,L,R,x);
        else if(R<=mid)update(2*node,L,R,x);
        else
        {
            update(2*node,L,mid,x);
            update(2*node+1,mid+1,R,x);
        }
        Pushup(node);
    }
    int bi(int x)
    {
        int L=1,R=num-1,mid;
        while(L<=R)
        {
            mid=(L+R)>>1;
            if(rec[mid]==x)return mid;
            else if(rec[mid]>x)R=mid-1;
            else L=mid+1;
        }
        return -1;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
        scanf("%d",&n);
        ll sum=0;
        int cnt=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&x1,&y3,&x2,&y2);
                if(x1>x2)swap(x1,x2);
                if(y3>y2)swap(y3,y2);
                rec[cnt] = line[cnt].l = x1;
                line[cnt].r = x2+1;
                line[cnt].h = y3;
                line[cnt++].flag = 1;
                line[cnt].l = x1;
                rec[cnt] = line[cnt].r = x2+1;
                line[cnt].h = y2+1;
                line[cnt++].flag = -1;
                if(x1==x2)sum=sum+abs(y2-y3)+1;
                else sum=sum+abs(x1-x2)+1;
        }
        sort(line+1,line+cnt,cmp);
        sort(rec+1,rec+cnt);
        num = 2;
        for(int i = 2;i < cnt;i++)
        {
            if(rec[i]!=rec[i-1])rec[num++]=rec[i];
        }
        build(1,1,num-1);
        ll ans=0;
        for(int i = 1;i < cnt-1;i++)
        {
            int fx = bi(line[i].l);
            int fy = bi(line[i].r)-1;
            if(fx <= fy)
            {
                update(1,fx,fy,line[i].flag);
            }
            ans+=tree[1].sum*(ll)(line[i+1].h-line[i].h);
        }
       // cout<<ans<<endl;
        //cout<<sum<<" ";
        printf("%lld
    ",sum-ans);
    }
        return 0;
    }
    

      

  • 相关阅读:
    vm 克隆一台新机器启动网卡报错:device eth0 does not seem to be present, delaying initialization
    DHCP server 冒充及DOS攻击处理方案
    linux、centos下查看系统版本、bios版本,内存信息等
    ubuntu 下当前网速查看
    ubuntu的文本界面修改字体大小
    mysql增加远程连接用户及查看数据库表结构
    数据库问题-复杂流量问题的排查
    python处理空格脚本
    winform水平滚动条联动panel
    winform自定义日期控件,要求可以手动输入日期DatePicker
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5784725.html
Copyright © 2011-2022 走看看