zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营6 H 云

    https://ac.nowcoder.com/acm/contest/3007/H

    神思路。。。

    倘若两片云能够相遇,那么把他们映射到y=-x上的线段相交

    为什么?

    第一象限往下,第三象限往右他们最先相交的那两个点的初始位置和交点位置构成一个等腰直角三角形

    如果没有这样的等腰直角三角形则不能相交

    y=-x与该三角形底边垂直

    所以两点初始位置向y=-x作垂线,垂足重合

    如何将矩形映射到y=-x上?

    将左上角和右上角这两个点向y=-x作垂线,根据等腰直角三角形推一推可得垂足的纵坐标为(y-x)/2

    除以2会产生小数,不用除效果是一样的

    然后问题转化成有一些A类线段和一些B类线段,求AB相交的线段对数

    扫描线

    将线段的端点从小到大排序

    分别记录当前A类线段、B类线段个数

    碰到线段左端点,对应类别线段个数+1,并累加当前另一种类别线段的个数

    即每次累计左端点在该线段之前并与该线段相交的线段个数

    碰到线段右端点,对应类别线段个数-1

    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    
    #define N 100001
    
    struct node
    {
        int pos,lr,ty;
        node(int pos_=0,int lr_=0,int ty_=0) : pos(pos_),lr(lr_),ty(ty_) {}
    }e[N<<2]; 
    
    int cnt[N];
    
    bool cmp(node p,node q)
    {
        if(p.pos==q.pos && p.lr==q.lr) return p.ty<q.ty;
        if(p.pos==q.pos) return p.lr>q.lr;
        return p.pos<q.pos;
    }
    
    int main()
    {
        int n,m,xa,ya,xb,yb,tot=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
            e[++tot]=node(yb-xb,1,0);
            e[++tot]=node(ya-xa,-1,0);
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
            e[++tot]=node(yb-xb,1,1);
            e[++tot]=node(ya-xa,-1,1);
        }
        sort(e+1,e+tot+1,cmp); 
        long long ans=0;
        for(int i=1;i<=tot;++i)
        {
            cnt[e[i].ty]+=e[i].lr;
            if(e[i].lr==1)  ans+=cnt[e[i].ty^1];
        }
        printf("%lld",ans);
    } 
  • 相关阅读:
    升级centos6.5系统的gcc为4.8.5的简易步骤
    赛车比赛(洛谷U4566)
    月考(cogs 1176)
    xth的旅行(codevs 1450)
    魔法禁书目录2:回家(codevs 3024)
    交换
    牛的旅行(洛谷 1522)
    长途旅行
    序列问题
    正确答案
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12363408.html
Copyright © 2011-2022 走看看