题意

有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. PHP面向对象——三大基本特性与五大基本原则

    三大特性是:封装.继承.多态 所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 封装是面向对象的特征之一,是对象和类概念的主要特 ...

  2. Redis事务及锁应用

    Redis只支持简单的事务,不像mysql那样比较完整严格,对数据的完整性也维持的很好.redis的开启事务实际上只是将开启事务之后的一段命令用队列包裹起来了,当调用redis的执行命令(exec)全 ...

  3. Unit01: JDBC原理 、 JDBC基础编程

    Unit01: JDBC原理 . JDBC基础编程 这个文件里面有两块内容: 1.用比较麻烦的方式连接数据库,test1(),test4() 2.创建DBTool,测试DBTool连接数据库 ,tes ...

  4. 数据运算+-*/,比较运算符==!=,赋值运算,逻辑运算and,or,not,成员运算in,not in,身份运算is is not,位运算&|,运算符的优先级

    取模就是返回余数. 取模的作用主要是来取奇偶数来用的,奇数干嘛,偶数干嘛. 比较运算符: 赋值运算: 逻辑运算: 赋值的时候可以多个变量同时赋值 成员运算: in就是在不在的意思. 身份运算: 位运算 ...

  5. Hibernate 一对一、一对多、多对多注解mappedBy属性的总结

    mappedBy: 所填内容必为本类在另一方的字段名. 表示:本类放弃控制关联关系,所有对关联关系的控制,如:建立.解除与另一方的关系,都由对方控制,本类不管.举个例子: Teacher和Studen ...

  6. 全连接BP神经网络

    前馈神经网络 前馈神经网络(feedforward neural network)是最朴素的神经网络,通常我们所说的前馈神经网络有两种,一种叫反向传播网络(Back propagation Netwo ...

  7. 【洛谷】P1754 球迷购票问题(基础dp)

    题目背景 盛况空前的足球赛即将举行.球赛门票售票处排起了球迷购票长龙. 按售票处规定,每位购票者限购一张门票,且每张票售价为50元.在排成长龙的球迷中有N个人手持面值50元的钱币,另有N个人手持面值1 ...

  8. OSPF理论介绍

    OSPF协议Open Shortest Path First是链路状态协议.RIP和EIGRP是距离矢量协议只知道邻居,但链路状态可知道全网信息,因此天然免疫环路.距离矢量协议和链路状态协议最大的区别 ...

  9. 关于Fiddler常见问题之一

    Fiddler设置代理后,手机无法上网常见检查项 1.检查IP 2.确认端口在工作   >  “ netstat -ano” 3.设置手机代理>管理网络设置>高级>代理服务器, ...

  10. mysql导出数据库数据及表结构

    1,导出远程数据库数据到本地 mysql -A wj_sms -h192.168.1.105 -uroot -p4321 -ss -e "set NAMES 'utf8';SELECT * ...