HDU 3465 线段树

来源:互联网 发布:汽车修理学习软件 编辑:程序博客网 时间:2024/06/10 15:53

点击打开链接

题意:给了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