【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 3 利用 Dlib 实现人脸检测和剪切
			
0. 引言 利用 Python 开发,借助 Dlib 库进行人脸检测 / face detection 和剪切: 1. crop_faces_show.py : 将检测到的人脸剪切下来,依次排序平 ...
 - javascript 中的 arguments,callee.caller,apply,call 区别
			
记录一下: 1.arguments是一个对象, 是函数的一个特性,只有在函数内才具有这个特性,在函数外部不用使用. 举例: function test(){ alert(typeof argume ...
 - 20 几个知名公司的 Java 面试题汇总
			
查看不同公司新鲜真实的Java面试题,摘自Glassdoor.com 巴克莱投资: 假设有一个 getNextparson() 方法返回 Person 对象,Person 类实现了 comparabl ...
 - Linux 解压 压缩 tar
			
tar 格式:tar [选项] 目录或文件 // 将 test 文件夹打包成 test.tar $ tar cvf test.tar test // 将 home 目录下的 test 文件夹打 ...
 - laravel的blade模板的布局嵌套
			
测试路由 Route::get('/', function() { $value = [,,]; return view('home.index', array('data' => $value ...
 - C语言的补码表示和unsigned及signed的转换
			
这东西实际编程时一直无视的,范围小了就换个大点的表示形式,但是总觉得基础知识还是掌握得好,免得到时候用移位运算或类型转换或笔试题时要花时间想. C语言的基本类型有char.int.float.doub ...
 - spring扩展点之一:BeanFactoryPostProcessor和BeanPostProcessor
			
一.BeanFactoryPostProcessor和BeanPostProcessor的区别 BeanFactoryPostProcessor和BeanPostProcessor都是spring初始 ...
 - open the flashback
			
1.打开flashback: 关闭数据库 启动到mount方式 SQL>startup mount; 如果归档没有打开,打开归档[因为flashback依赖Media recovery,所以在打 ...
 - yum问题的解决办法
			
关于使用yum“The program package-cleanup is...”的解决办法 在使用yum 时总是有提示信息: The program package-cleanup is f ...
 - 根据段落编号自动添加书签的VBA
			
Sub 宏1() ' ' 宏1 宏 ' ' Dim myRange As Word.Range Dim num As String, content As String Selection.Ho ...