zoukankan      html  css  js  c++  java
  • 【HDU5862】Counting Intersections

    题意

      有n条线段,且都平行于坐标轴。对于每条线段,给出两个端点的坐标。问一共有多少个线段的交点。

    分析

      最最简单的扫描法了。用线段树或者树状数组都可以。

      由题目可知,线段只有两种,要么平行于x轴要么平行于y轴。而交点只能是两个不平行的线段产生的。

      所有我们以一条平行于x轴的线为扫描线,从下向上扫。先把横坐标进行离散化,然后把平行于y轴的线段拆成上下两个端点。当扫到下端点的时候就在它横坐标+1,当扫到上端点的时候,就在它横坐标-1.对于每一条平行于x轴的线,则将左右端点内的值相加。就酱~

      这里一个小细节是,如果是下端点,则先更新,再计算。如果是上端点,则先计算再更新。

      讲真,这个题让我很难受,本来以为很快就能解决的题结果TLE了一晚上,刚刚才发现,是数组开小了(;´༎ຶД༎ຶ`) 

    线段树

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cmath>
     6 using namespace std;
     7 typedef long long LL;
     8 const int maxn=100000+100;
     9 struct Point {
    10     int j;//1,0,-1
    11     int x,h;
    12     int l,r;
    13     bool operator <(const Point &rhs)const {
    14         return h<rhs.h||(h==rhs.h&&j>rhs.j);
    15     }
    16 }seg[2*maxn];
    17 int T,n,x1,y1,x2,y2,sz,sk;
    18 LL ans;
    19 int v[2*maxn],sumv[8*maxn];
    20 int vv,x;
    21 void update(int o,int L,int R){
    22     if(L==R){
    23         sumv[o]+=vv;
    24         return ;
    25     }
    26     int M=L+(R-L)/2;
    27     if(x<=M) update(2*o,L,M);
    28     if(x>M) update(2*o+1,M+1,R);
    29     sumv[o]=sumv[2*o]+sumv[2*o+1];
    30     return ;
    31 }
    32 int ql,qr;
    33 int query(int o,int L,int R){
    34     if(ql<=L&&qr>=R){
    35         return sumv[o];
    36     }
    37     int res=0;
    38     int M=L+(R-L)/2;
    39     if(ql<=M)
    40         res+=query(2*o,L,M);
    41     if(qr>M)
    42         res+=query(2*o+1,M+1,R);
    43     return res;
    44 }
    45 int main(){
    46     scanf("%d",&T);
    47     for(int t=1;t<=T;t++){
    48         sz=sk=ans=0;
    49         scanf("%d",&n);
    50         for(int i=1;i<=n;i++){
    51             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    52             if(x1>x2||y1>y2){
    53                 swap(x1,x2);
    54                 swap(y1,y2);
    55             }
    56             if(x1==x2){
    57                 seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=1;
    58                 seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-1;
    59                 v[++sk]=x1;
    60             }else if(y1==y2){
    61                 seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=0;
    62                 v[++sk]=x1,v[++sk]=x2;
    63             }
    64         }
    65         sort(seg+1,seg+1+sz);
    66         sort(v+1,v+1+sk);
    67         int N=unique(v+1,v+1+sk)-v-1;
    68         memset(sumv,0,sizeof(sumv));
    69         for(int i=1;i<=sz;i++){
    70             if(seg[i].j==0){
    71                 ql=lower_bound(v+1,v+1+N,seg[i].l)-v;
    72                 qr=lower_bound(v+1,v+1+N,seg[i].r)-v;
    73                 ans+=query(1,1,N);
    74             }else{
    75                 vv=seg[i].j;x=lower_bound(v+1,v+1+N,seg[i].x)-v;
    76                 update(1,1,N);
    77             }
    78         }
    79         printf("%lld
    ",ans);
    80     }
    81 return 0;
    82 }
    View Code

      

    树状数组

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 
     8 const int maxn=100000+100;
     9 struct Point {
    10     int j;//1,0,-1
    11     int x,h;
    12     int l,r;
    13     bool operator <(const Point &rhs)const {
    14         return h<rhs.h||(h==rhs.h&&j>rhs.j);
    15     }
    16 }seg[2*maxn];
    17 int T,n,x1,y1,x2,y2,sz,sk,N;
    18 long long ans,C[2*maxn];
    19 int v[2*maxn];
    20 int lowbit(int x){
    21     return x&(-x);
    22 }
    23 void add(int x,int d){
    24     while(x<=N){
    25         C[x]+=d;
    26         x+=lowbit(x);
    27     }
    28 }
    29 long long sum(int x){
    30     long long res=0;
    31     while(x>0){
    32         res+=C[x];
    33         x-=lowbit(x);
    34     }
    35     return res;
    36 }
    37 int main(){
    38     scanf("%d",&T);
    39     for(int t=1;t<=T;t++){
    40         sz=sk=ans=0;
    41         scanf("%d",&n);
    42         for(int i=1;i<=n;i++){
    43             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    44             if(x1>x2||y1>y2){
    45                 swap(x1,x2);
    46                 swap(y1,y2);
    47             }
    48             if(x1==x2){
    49                 seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=1;
    50                 seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-1;
    51                 v[++sk]=x1;
    52             }else if(y1==y2){
    53                 seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=0;
    54                 v[++sk]=x1,v[++sk]=x2;
    55             }
    56         }
    57         sort(seg+1,seg+1+sz);
    58         sort(v+1,v+1+sk);
    59         N=unique(v+1,v+1+sk)-v-1;
    60 
    61         for(int i=1;i<=sz;i++){
    62              if(seg[i].j==0){
    63                 int l=lower_bound(v+1,v+1+N,seg[i].l)-v;
    64                 int r=lower_bound(v+1,v+1+N,seg[i].r)-v;
    65               //  cout<<l<<" "<<r<<endl;
    66                 ans+=sum(r)-sum(l-1);
    67              }
    68              else{
    69                 int x=lower_bound(v+1,v+1+N,seg[i].x)-v;
    70              //   cout<<x<<" "<<seg[i].j<<endl;
    71                 add(x,seg[i].j);
    72              }
    73         }
    74         printf("%lld
    ",ans);
    75     }
    76 return 0;
    77 }
    View Code
  • 相关阅读:
    [NOTE]常用Linux命令总结[Thx for commandlinefu]
    [原]隧道Proxy原理详解(基于Node.js)
    [转]MySQL索引详解(1)
    [QA]服务端进程模型
    [转]MySQL索引详解(2)
    非动态规划实现LCS算法
    Java里线程安全的有界容器的实现
    maven历史版本下载
    JDK9下载
    maven排除依赖和添加本地依赖
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9040342.html
Copyright © 2011-2022 走看看