题意

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

分析

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

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

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

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

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

线段树

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int maxn=+;
struct Point {
int j;//1,0,-1
int x,h;
int l,r;
bool operator <(const Point &rhs)const {
return h<rhs.h||(h==rhs.h&&j>rhs.j);
}
}seg[*maxn];
int T,n,x1,y1,x2,y2,sz,sk;
LL ans;
int v[*maxn],sumv[*maxn];
int vv,x;
void update(int o,int L,int R){
if(L==R){
sumv[o]+=vv;
return ;
}
int M=L+(R-L)/;
if(x<=M) update(*o,L,M);
if(x>M) update(*o+,M+,R);
sumv[o]=sumv[*o]+sumv[*o+];
return ;
}
int ql,qr;
int query(int o,int L,int R){
if(ql<=L&&qr>=R){
return sumv[o];
}
int res=;
int M=L+(R-L)/;
if(ql<=M)
res+=query(*o,L,M);
if(qr>M)
res+=query(*o+,M+,R);
return res;
}
int main(){
scanf("%d",&T);
for(int t=;t<=T;t++){
sz=sk=ans=;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1>x2||y1>y2){
swap(x1,x2);
swap(y1,y2);
}
if(x1==x2){
seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=;
seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-;
v[++sk]=x1;
}else if(y1==y2){
seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=;
v[++sk]=x1,v[++sk]=x2;
}
}
sort(seg+,seg++sz);
sort(v+,v++sk);
int N=unique(v+,v++sk)-v-;
memset(sumv,,sizeof(sumv));
for(int i=;i<=sz;i++){
if(seg[i].j==){
ql=lower_bound(v+,v++N,seg[i].l)-v;
qr=lower_bound(v+,v++N,seg[i].r)-v;
ans+=query(,,N);
}else{
vv=seg[i].j;x=lower_bound(v+,v++N,seg[i].x)-v;
update(,,N);
}
}
printf("%lld\n",ans);
}
return ;
}

树状数组

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream> using namespace std; const int maxn=+;
struct Point {
int j;//1,0,-1
int x,h;
int l,r;
bool operator <(const Point &rhs)const {
return h<rhs.h||(h==rhs.h&&j>rhs.j);
}
}seg[*maxn];
int T,n,x1,y1,x2,y2,sz,sk,N;
long long ans,C[*maxn];
int v[*maxn];
int lowbit(int x){
return x&(-x);
}
void add(int x,int d){
while(x<=N){
C[x]+=d;
x+=lowbit(x);
}
}
long long sum(int x){
long long res=;
while(x>){
res+=C[x];
x-=lowbit(x);
}
return res;
}
int main(){
scanf("%d",&T);
for(int t=;t<=T;t++){
sz=sk=ans=;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1>x2||y1>y2){
swap(x1,x2);
swap(y1,y2);
}
if(x1==x2){
seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=;
seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-;
v[++sk]=x1;
}else if(y1==y2){
seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=;
v[++sk]=x1,v[++sk]=x2;
}
}
sort(seg+,seg++sz);
sort(v+,v++sk);
N=unique(v+,v++sk)-v-; for(int i=;i<=sz;i++){
if(seg[i].j==){
int l=lower_bound(v+,v++N,seg[i].l)-v;
int r=lower_bound(v+,v++N,seg[i].r)-v;
// cout<<l<<" "<<r<<endl;
ans+=sum(r)-sum(l-);
}
else{
int x=lower_bound(v+,v++N,seg[i].x)-v;
// cout<<x<<" "<<seg[i].j<<endl;
add(x,seg[i].j);
}
}
printf("%lld\n",ans);
}
return ;
}

【HDU5862】Counting Intersections的更多相关文章

  1. 【题解】Counting D-sets(容斥+欧拉定理)

    [题解]Counting D-sets(容斥+欧拉定理) 没时间写先咕咕咕. vjCodeChef - CNTDSETS 就是容斥,只是难了一二三四五\(\dots \inf\)点 题目大意: 给定你 ...

  2. 【LeetCode】Counting Bits(338)

    1. Description Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num ...

  3. 【CSA35G】【XSY3318】Counting Quests DP 拉格朗日反演 NTT

    题目大意 zjt 是个神仙. 一天,zjt 正在和 yww 玩猜数游戏. zjt 先想一个 \([1,n]\) 之间的整数 \(x\),然后 yww 开始向他问问题. yww 每次给 zjt 一个区间 ...

  4. 【xsy2479】counting 生成函数+多项式快速幂

    题目大意:在字符集大小为$m$的情况下,有多少种构造长度为$n$的字符串$s$的方案,使得$C(s)=k$.其中$C(s)$表示字符串$s$中出现次数最多的字符的出现次数. 对$998244353$取 ...

  5. 【HDOJ5952】Counting Cliques(团,dfs)

    题意:给定一张n点m边的图,求大小为S的团的个数 N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10,保证点的度不超过20 思路:dfs 因为每个点可能不止属于一个极大团,所以不能求出极大团然后计 ...

  6. 【HDU5952】Counting Cliques

    题目大意:给定一个\(N\)个点,\(M\)条边的无向图,求图中有多少个大小为\(S\)的团.\(N \le 100,deg(i)\le 20,i\in [1,n]\). 题解: 考虑搜索. 需要确定 ...

  7. 【LeetCode】位运算 bit manipulation(共32题)

    [78]Subsets 给了一个 distinct 的数组,返回它所有的子集. Example: Input: nums = [,,] Output: [ [], [], [], [,,], [,], ...

  8. 【题解】晋升者计数 Promotion Counting [USACO 17 JAN] [P3605]

    [题解]晋升者计数 Promotion Counting [USACO 17 JAN] [P3605] 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训.!牛是可怕的管理者! [题目描 ...

  9. 【概率论】1-2:计数方法(Counting Methods)

    title: [概率论]1-2:计数方法(Counting Methods) categories: Mathematic Probability keywords: Counting Methods ...

随机推荐

  1. MySQL中地理位置数据扩展geometry的使用心得

    最近学习了些MySQL geometry数据存储和计算,在这里记录下. 1. 环境 geometry推荐在5.6版本以上使用,尽管大部分功能在5.5已经可用,除了距离计算函数st_distance等新 ...

  2. luarocks 安装

    1. linux 安装 wget https://luarocks.org/releases/luarocks-2.4.1.tar.gz tar zxpf luarocks-2.4.1.tar.gz ...

  3. 分享Win7 将svn增加系统服务并成功启动的方法

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/default7/article/details/32728717 依照网上搜索到的方法,结果一直提示 ...

  4. Hbase 之 HBase 的整体架构

    HBase 系统架构图 组成部件说明  Client:  使用HBase RPC机制与HMaster和HRegionServer进行通信  Client与HMaster进行通信进行管理类操作  Cli ...

  5. onclick监听

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. MIT App Inventor使用与入门教程

    前言:随着信息技术新课标的提出,移动app应用设计被加入到新课标,程序与算法得到体现,学生的创造性,计算思维与信息意识也可以在其中得到体现. 安卓app开发目前比较火热的是Eclipse和Androi ...

  7. 1、spark集群搭建

    前提:已经搭建完全分布式的Hadoop集群,请参看http://www.cnblogs.com/netbloomy/p/6660131.html 1.Scala2.12.1环境搭建 1).下载scal ...

  8. 对SQLite数据库操作 操作db文件

    sqlite数据库就是一个DB文件.  程序每操作一次数据库都要读一次 .DB  文件 .  这个文件就是这个SQLite数据库. 如果需要依赖包的可以联系我 工具类: package com.hot ...

  9. Java运算符,算术运算符

    算术运算符介绍 算术运算符用在数学表达式中,它们的作用和在数学中的作用一样. 下表列出了所有的算术运算符. 表格中的实例假设整数变量A的值为10,变量B的值为20: 操作符 描述 例子 + 加法 - ...

  10. orzdba_monitor.sh和orzdba

    1.脚本 #!/bin/bash # line: V1.0 # mail: gczheng@139.com # data: 2018-04-23 # script_name: orzdba_monit ...