HDU 3465 线段树

点击打开链接

题意:给了n条直线,问你在开区间L到R中有多少对直线的交点

思路:大神们的智商不是我等可以理解的(/ □ \),那么怎么写呢,看一看线段相交的充分条件,(x1-x2)*(y1-y2)<0,哦原来如此,可以看出这就是逆序数呦西,那就求逆序数就可以了,处理细节很麻烦,不跟着大神的题解走的话,肯定会掉坑里去,还有一个就是对于在这个区间里的平行于y轴的直线,肯定与那些非平行于y轴的直线有交点,直接算一下就行了,看代码把

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int num[maxn<<2];
void update(int pos,int add,int le,int ri,int node){
    if(le==ri){
        num[node]+=add;
        return ;
    }
    int t=(le+ri)>>1;
    if(pos<=t) update(pos,add,le,t,node<<1);
    else update(pos,add,t+1,ri,node<<1|1);
    num[node]=num[node<<1]+num[node<<1|1];
}
int query(int l,int r,int le,int ri,int node){
    if(l<=le&&ri<=r) return num[node];
    int t=(le+ri)>>1,ans=0;
    if(l<=t) ans+=query(l,r,le,t,node<<1);
    if(r>t) ans+=query(l,r,t+1,ri,node<<1|1);
    return ans;
}
struct edge{
    double l,r;
    int pos;
}id[maxn];
bool cmp1(const edge &a,const edge &b){
    return a.l<b.l;
}
bool cmp2(const edge &a,const edge &b){
    return a.r<b.r;
}
int main(){
    int n;
    double L,R,l1,l2,r1,r2;
    while(scanf("%d",&n)!=-1){
        memset(num,0,sizeof(num));
        scanf("%lf%lf",&L,&R);
        int sum=0,k=0,cnt=0;
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&l1,&r1,&l2,&r2);
            if(l1==l2){
                if(l1>L&&l1<R) sum++;
            }else{
                double t1=l2-l1,t2=r2-r1;
                double y=(t2*L-t2*l1+t1*r1)/t1;
                double y1=(t2*R-t2*l1+t1*r1)/t1;
                id[k].l=y;id[k++].r=y1;
            }
        }
        sort(id,id+k,cmp1);id[0].pos=1;
        int tt=1,ans1=0;
        for(int i=1;i<k;i++){
            if(id[i].l==id[i-1].l) id[i].pos=tt;//对于重复的点,进行去重这样下面的边界会好处理的多
            else id[i].pos=++tt;
        }
        sort(id,id+k,cmp2);
        for(int i=0;i<k;i++){
            update(id[i].pos,1,1,tt,1);
            if(id[i].pos==tt) continue;//就是这里,因为R是不算进结果的,那么就从下一个开始算逆序数
            else ans1+=query(id[i].pos+1,tt,1,tt,1);
        }
        int ans=ans1+sum*k;
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值