【HDU5862】Counting Intersections
题意
有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的更多相关文章
- 【题解】Counting D-sets(容斥+欧拉定理)
[题解]Counting D-sets(容斥+欧拉定理) 没时间写先咕咕咕. vjCodeChef - CNTDSETS 就是容斥,只是难了一二三四五\(\dots \inf\)点 题目大意: 给定你 ...
- 【LeetCode】Counting Bits(338)
1. Description Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num ...
- 【CSA35G】【XSY3318】Counting Quests DP 拉格朗日反演 NTT
题目大意 zjt 是个神仙. 一天,zjt 正在和 yww 玩猜数游戏. zjt 先想一个 \([1,n]\) 之间的整数 \(x\),然后 yww 开始向他问问题. yww 每次给 zjt 一个区间 ...
- 【xsy2479】counting 生成函数+多项式快速幂
题目大意:在字符集大小为$m$的情况下,有多少种构造长度为$n$的字符串$s$的方案,使得$C(s)=k$.其中$C(s)$表示字符串$s$中出现次数最多的字符的出现次数. 对$998244353$取 ...
- 【HDOJ5952】Counting Cliques(团,dfs)
题意:给定一张n点m边的图,求大小为S的团的个数 N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10,保证点的度不超过20 思路:dfs 因为每个点可能不止属于一个极大团,所以不能求出极大团然后计 ...
- 【HDU5952】Counting Cliques
题目大意:给定一个\(N\)个点,\(M\)条边的无向图,求图中有多少个大小为\(S\)的团.\(N \le 100,deg(i)\le 20,i\in [1,n]\). 题解: 考虑搜索. 需要确定 ...
- 【LeetCode】位运算 bit manipulation(共32题)
[78]Subsets 给了一个 distinct 的数组,返回它所有的子集. Example: Input: nums = [,,] Output: [ [], [], [], [,,], [,], ...
- 【题解】晋升者计数 Promotion Counting [USACO 17 JAN] [P3605]
[题解]晋升者计数 Promotion Counting [USACO 17 JAN] [P3605] 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训.!牛是可怕的管理者! [题目描 ...
- 【概率论】1-2:计数方法(Counting Methods)
title: [概率论]1-2:计数方法(Counting Methods) categories: Mathematic Probability keywords: Counting Methods ...
随机推荐
- python模块--hashlib
用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法 import hashlib m = hashlib.m ...
- C#类、方法的访问修饰符
这篇文章主要介绍了C#类的访问修饰符用法,较为详细的分析了C#类的访问修饰符概念与用法,具有一定的参考借鉴价值,需要的朋友可以参考下 本文详细分析了C#类的访问修饰符用法,分享给大家供大家参考.具体用 ...
- 你真的了解分层架构吗?——写给被PetShop"毒害"的朋友们
一叶障目 .NET平台上的分层架构(很多朋友称其为“三层架构”),似乎是一个长盛不衰的话题.经常看到许多朋友对其进行分析.探讨.辩论甚至是抨击.笔者在仔细阅读了大量这方面文章后,认为许多朋友在分层架构 ...
- 关于1024:堆栈下溢的错误(1024. Stack Underflow Occurred)
http://blog.163.com/sylar_lin/blog/static/192332093201111242412487/ 今天碰到个很奇怪的问题,注释掉下面的trace,realse版本 ...
- springboot: 使web项目支持jsp
1.springboot为什么不推荐使用jsp? 参考地址:https://spring.io/blog/2012/10/30/spring-mvc-from-jsp-and-tiles-to-thy ...
- RK3288 增加双屏异显 eDP+LVDS
CPU:RK3288 系统:Android 5.1 下面是官方文档中的信息. 1.rk3288 支持的显示接口可以任意组合. 2.双屏异显时,一个显示接口当主屏,另一个当副屏:主副屏由板级 dts 文 ...
- 从汇编的角度看待const与#define
先观察一下的代码: #include<stdio.h> int main(){ ; int y; int *pi=(int*)&i; *pi=; y=*pi; int tempi; ...
- 轻量级封装DbUtils&Mybatis之四MyBatis主键
MyBatis主键 不支持对象列表存储时对自增id字段的赋值(至少包括3.2.6和3.3.0版本),如果id不是采用底层DB自增主键赋值,不必考虑此问题 温馨提示:分布式DB环境下,DB主键一般会采用 ...
- C语言中可变形参简单实例
以下程序主要包括三个主要函数: 一个最简单的可变形参函数实例: 一个简单的printf功能的实例: 一个打印字符串函数(辅助): 其中myPrintf函数,实现了printf的部分简单功能,并没有去实 ...
- Java并发-Runnable、Callable、Future、Future Task
Runnable: Runnable的代码非常简单,他是一个接口,且接口中只有一个方法,run(),创建一个类实现他,把一些费时操作写在其中,然后使用某个线程去执行该Runnable实现类即可实现多线 ...