NKOJ-Unknow 直线的交点
来源:互联网 发布:三菱系统攻丝编程实例 编辑:程序博客网 时间:2024/06/14 11:23
直线的交点
问题描述
伦伦刚刚在高中学习了解析几何,学会了计算两条直线的交点。这天,老师给她布置了一道作业。在平面上有 n 条直线,他们之间有若干交点。给定一对平板(两条平行的直线),问这有多少对直线,他们的交点在这一对平板之间(注意 (i, j) 和 (j, i) 只算一对)。
输入格式
第一行三个整数 k,a,b 表示平板的两条平行直线的方程为 y=kx+a 和 y=kx+b,保证 a<b。第二行一个整数 n。接下来 n 行每行两个整数 ki,bi 表示第 i 条直线的方程 y=kix+bi。
输出格式
一个整数,表示有多少对直线,他们的交点在平板之间。
样例输入
0 3 5051 02 0-1 0-2 0-1 10
样例输出
3
样例解释
只有 y=-x+10 这条直线和 y=x,y=2x,y=-2x 这三条直线的交点在区域内。
数据范围与约定
对于 30% 的数据, n≤5000。对于 100% 的数据, n≤100000。为了简单起见,输入数据保证,没有直线和平板平行,没有两条直线的交点在平板上。
像这种题就是给我做我都不会做
题解
简化题意
由于上下两条线是平行的
所以 可以自己画两条平行线
然后按照和上平行线的交点的顺序 一条一条加进去
然后你就会惊奇地发现
每加入一条直线 新增的交点数=之前的直线数量-加入的直线与下平行线交点的左边的交点数
没什么好证明的 观察就能知道是为什么
假设直线LA与上平行线的交点在LB与上平行线的交点左边那么 LB与下平行线的交点在LA与下平行线的交点的左边时 就有交点 反之则没有
而上面 之前的直线数量-加入的直线与下平行线交点的左边的交点数 即为 与下平行线的交点在多少条直线的左边
注意 我们是按照和上平行线交点的顺序依次加入直线的 所以上述证明过程绝对可以普遍化
于是 这就变成了一道简单的树状数组题
解法
求出每条直线和上下平行线的交点 并按照和上平行线的交点的顺序排序
对于每条直线
统计 之前的直线数量-当前直线与下平行线交点的左边的交点数 ->加入结果将当前的下交点加入树状数组
而下交点的位置需要离散化 即 它的新位置由 排序后 lower_bound求出的位置 表示
总结
这道题目其实很简单 关键在于对交点数判定的简化过程(其实这个过程中考好像就有涉及)
其次的操作是离散化 这个操作很普遍 需要熟练掌握
附上对拍代码(比题解麻烦很多,最好不要看)
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#define mid (l+r>>1)#define lowbit(x) (x&-x)using namespace std;inline int input(){ char c=getchar();int o;bool f=0; while(c>57||c<48)f|=(c=='-'),c=getchar(); for(o=0;c>47&&c<58;c=getchar())o=(o<<1)+(o<<3)+c-48; return f?-o:o;}struct li{double k,b;}line[101234],nline,up,down;struct cut{double a,b;int mk;}pots[101234];bool cp(cut a,cut b){return a.a<b.a;}double dx,pot[201234];int all=0,ap,ll,rr,p;int shang[201234],xia[201234];void add(cut a){ for(int x=a.a;x<=ap;x+=lowbit(x))shang[x]++; for(int x=a.b;x<=ap;x+=lowbit(x))xia[x]++;}int sum(cut a){ int ansA=0,ansB=0; for(int x=a.a;x;x-=lowbit(x))ansA+=shang[x]; for(int x=a.b;x;x-=lowbit(x))ansB+=xia[x]; return abs(ansA-ansB);}double jiao(li a,li b){return (b.b-a.b)/(a.k-b.k);}void addp(li a){ pots[++all].a=jiao(a,down); pots[all].b=jiao(a,up)+dx;}int main(){ freopen("point.in","r",stdin); freopen("point.out","w",stdout); int n;long long res=0; double k; k=down.k=up.k=input();down.b=input();up.b=input(); dx=(up.b-down.b)*k/(1+k*k); n=input(); for(int i=1;i<=n;i++)nline.k=input(),nline.b=input(),addp(nline); for(int i=1;i<=n;i++)pot[i<<1]=pots[i].b,pot[(i<<1)-1]=pots[i].a; ap=all<<1; sort(pot+1,pot+ap+1); for(int i=1;i<=n;i++) { pots[i].a=lower_bound(pot+1,pot+ap+1,pots[i].a)-pot; pots[i].b=lower_bound(pot+1,pot+ap+1,pots[i].b)-pot; } sort(pots+1,pots+all+1,cp); for(int i=1;i<=all;i++) { res+=sum(pots[i]); add(pots[i]); } printf("%lld",res);}
阅读全文
0 0
- NKOJ-Unknow 直线的交点
- [高效] NKOJ 4251 直线的交点
- NKOJ-Unknow 死亡的颂唱者
- NKOJ-Unknow 不死的 LYM
- 直线的交点公式
- 直线的交点
- NKOJ-Unknow 2357数
- NKOJ-Unknow 回文数
- NKOJ-Unknow 监狱
- NKOJ-Unknow 幸运数字
- 计算直线的交点数
- 求两直线的交点
- 计算直线的交点数
- 求两直线的交点
- 直线和平面的交点
- c++求两条直线的交点
- POJ 1269(直线的交点)
- 计算直线的交点数
- Spark2.x学习笔记:11、RDD依赖关系与stage划分
- Ajax
- bzoj1289: [CTSC2009]移盘子
- 畅通工程再续 HDU
- Remove Element
- NKOJ-Unknow 直线的交点
- poj 1149 建模(dinic算法求最)
- Bigdecimal用法
- 转发和重定向
- sharding-jdbc读写分离原理解读
- 程序员谈恋爱的故事(一)
- Awaitility用户指导
- Python数据分析之numpy学习(二)
- 继续畅通工程 HDU