【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 ...
随机推荐
- Spring boot admin 使用
1. maven依赖 <dependencies> <dependency> <groupId>org.springframework.boot</group ...
- zk中文乱码问题
之前讲了怎么把数据导入到zookeeper(见zookeeper事件监听的importData方法),虽然本机win10的zookeeper展示没问题,但到了linux上就出现乱码了: << ...
- golang的beego框架开发时出现的问题纪录
golang的beego框架开发时出现的问题纪录1.数据库并发时问题:[ORM]2017/02/20 23:44:05 -[Queries/default] - [FAIL / db.Query / ...
- linux mount / umount 命令的基本用法 及 开机自动挂载
格式:mount [-参数] [设备名称] [挂载点] 其中常用的参数有: -a 安装在/etc/fstab文件中类出的所有文件系统. -f 伪装mount,作出检查设备和目录的样子,但并不真正挂载文 ...
- cocos2d js 利用texture packer生成sprite
cc.spriteFrameCache.addSpriteFrames(res.winLose_plist,res.winLose_png); var frame = cc.spriteFrameCa ...
- ConcurrentLinkedQueue 模拟火车售票过程
火车票类 public class Ticket { private String NO; // 车票编号 private double price; // 票价 public Ticket(Stri ...
- (转)Inno Setup入门(六)——在程序目录下创建文件夹
本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17250789 创建文件夹可以使用[dirs]段实现,代码如下: [s ...
- Django 组件-cookie与session
Cookie概述 什么叫Cookie Cookie翻译成中文是小甜点,小饼干的意思.在HTTP中它表示服务器送给客户端浏览器的小甜点.其实Cookie是key-value结构,类似于一个python中 ...
- 读jQuery之二十(Deferred对象)--(转)
原博文地址:http://www.cnblogs.com/snandy/archive/2012/12/19/2812935.html Deferred对象是由.Deferred构造的,.Deferr ...
- 【UVA】1595 Symmetry(模拟)
题目 题目 分析 理清思路,上模拟. 代码 #include <bits/stdc++.h> using namespace std; const int maxn=100 ...