集训考试题tents
题目描述
Pb 去郊游啦!他来到一块空地打算在这里搭一个帐篷。
但是,帐篷的四个支撑点不能在落在任何位置上,而只能落在一些固定点上。现在,他找到地面上有 N 个点可以支撑帐篷。(四个支撑点必须围成一个矩形) 他想知道依次每加多一个点,搭帐篷的方法数。
输入格式
第1行:一个整数N
第2行至N+1行:每行有两个整数的x, y作为一个点的坐标。
输出格式
共N行:第i行表示当前加入第i个点后可以搭帐篷的方案数。
这题的关键在于如何判断任意四个点是矩形。
在数学上,矩形的判定有4种方式
1.有三个角是直角的四边形是矩形;
2.对角线互相平分且相等的四边形是矩形;
3.有一个角为直角的平行四边形是矩形;
4.对角线相等的平行四边形是矩形。
于是显然我们可以看出来,第一种和第三种方法肯定时候超时的
而第二种和第四种,从本质上讲,我们在是实现时是一样的
于是现在的问题是我们要如何快速判断对角线相等且平分

我们可以知道的是合法的对角线一定是这样的,对于一个矩形的两条对角线,我们可以知道他们的交叉点是相等的
而这个交叉点的横坐标是如图确定出一条对角线的两个点横坐标的和的一半,纵坐标同理
所以我们要先解决这个点,但是接着,问题出现了,只靠这一个信息是不够的。
我们目前有两个选择:
1.获取足够多的可以确定是矩形的信息
2.将三个点(矩形的两个顶点和对角线的中点)统一成一个值
显然我们肯定不愿意写第一种,因为很麻烦
所以我们可以利用第二种方式,于是我们很自然的想到了hash,为了保证答案的准确,我们只需要准备一个足够复杂和hash函数即可
而每一个hash过的数,我们用挂链法记录下来,若碰到了两个相等或是误差极小hash值,我们可以确定这四个点可以构成一个矩形,答案数加一
具体实现见代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = ;
const int mod = ;
const double cri = 0.0000001;
struct enkidu {
double x, y;
}a[maxn];
struct Shiki {//Ryougi
double x, y, z;
int net;
}e[mod + ];
int n, ans = ;
int ha[mod + ], len = ; inline int read() {
int x = , y = ;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') y = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + ch - '';
ch = getchar();
}
return x * y;
} inline void insert(ll kk, double xx, double yy, double zz) {
e[++len].x = xx;
e[len].y = yy;
e[len].z = zz;
e[len].net = ha[kk];
ha[kk] = len;
} inline bool check(double a, double b) {
if(abs(a - b) < cri) return ;
else return ;
} inline void hash(double x, double y, double z) {
ll k = x * y + y * z + x * z + x + y + z + mod;
if(k < ) k = -k;
k %= mod;
//cout << k << '\n';
for(int i = ha[k]; i; i = e[i].net)
if(check(x, e[i].x) && check(y, e[i].y) && check(z, e[i].z))
ans++;
insert(k, x, y, z);
} int main() {
n = read();
for(int i = ; i <= n; ++i)
a[i].x = read(), a[i].y = read();
for(int i = ; i <= n; ++i) {
double x, y, z;
for(int j = ; j < i; ++j) {
x = (a[i].x + a[j].x) / ;
y = (a[i].y + a[j].y) / ;
z = ((a[i].x - a[j].x) * x + (a[i].y - a[j].y) * y) / (a[i].x + a[j].y);
hash(x, y, z);
}
cout << ans << '\n';
}
return ;
}
目前接到反映加实测,上面那份代码好像死了....我....天知道发生了什么....
下面随便摆一份Ac的(hash函数不同
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = ;
const int mod = ;
struct node {
double x, y;
}a[maxn];
struct nn {
double x, y, z;
ll net;
}e[mod + ];
int n;
int lin[mod + ];
int tot = , ans = ;
double x, y, z; inline bool pd(double a, double b) {
if(abs(a - b) < 0.000000001) return ;
return ;
} inline void insert(double x, double y, double z, ll k) {
e[++tot].x = x;
e[tot].y = y;
e[tot].z = z;
e[tot].net = lin[k];
lin[k] = tot;
} inline void hash(double x, double y, double z) {
ll k = x * y + y * z + x * z + x + y + z + mod;
if(k < ) k = -k;
k %= mod;
// cout << 'k' << ':' << k <<'\n';
for(int i = lin[k]; i; i = e[i].net)
if(pd(e[i].x, x) && pd(e[i].y, y) && pd(e[i].z, z))
ans++;
insert(x, y, z, k);
} int main() {
// freopen("tents.in", "r", stdin);
// freopen("tents.out", "w", stdout);
cin >> n;
for(int i = ; i <= n; i++) {
cin >> a[i].x >> a[i].y;
for(int j = ; j < i; ++j) {
x = (a[i].x + a[j].x) / ;
y = (a[i].y + a[j].y) / ;
z = (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y);
hash(x, y, z);
}
cout << ans << '\n';
}
fclose(stdin);
fclose(stdout);
return ;
集训考试题tents的更多相关文章
- 集训考试题(CF510C Fox And Names的简化版)
题目描述给定n个由小写字母组成的字符串,请你求出一个字母表顺序,使得这n个字符串是按照字典序升序排列的,数据保证存在合法的字母表顺序.如果存在多个解,输出字典序最小的那个. 输入格式第一行一个整数n. ...
- 好题Islands
Orz yjc 吊打候选队 不好的思路是枚举森林的m块,这样DP显然会涉及n当做某一维,最多只能卷积优化一下 生成函数什么的n太大不用想 考虑m,k比较小,能不能把n变成一个系数,而不是维度 所以就是 ...
- [日常] NOIP前集训日记
写点流水账放松身心... 10.8 前一天考完NHEEE的一调考试终于可以开始集训了Orz (然后上来考试就迟到5min, GG) T1维护队列瞎贪心, 过了大样例交上去一点也不稳...T出翔只拿了5 ...
- 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!
前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...
- 佳木斯集训Day1
23333第一次写博客 其实在佳木斯集训之前我都已经两三个月没打代码了 在佳木斯的时候前几天真心手生,导致了前几次考试考的很差... D1的考试还是比较良心的,T1是一道大模拟,直接枚举最后几位是00 ...
- 「疫期集训day3」要塞
战友们正讨论着他们曾经参加过凡尔登战役的父亲...在黎明前我们必须誓死坚守----法乌克斯要塞中弹尽粮绝的法军士兵 什么!今天又考状压和tarjan! 达成成就:连续两天复习数论和二分图 康乐康,这次 ...
- QDEZ集训笔记【更新中】
这是一个绝妙的比喻,如果青岛二中的台阶上每级站一只平度一中的猫,差不多站满了吧 自己的理解 [2016-12-31] [主席树] http://www.cnblogs.com/candy99/p/61 ...
- 2015UESTC 暑假集训总结
day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...
- JS省队集训记
不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...
随机推荐
- 【题解】SDOI2016征途
就放个代码吧……实在是太套路了.不过据说有复杂度还要低很多的算法,不知道是怎么做呀…… #include <bits/stdc++.h> using namespace std; #def ...
- 【BZOJ 2879】[Noi2012]美食节 费用流
思路同修车,就是多了一个骚气的操作:动态加边,我们通过spfa流的过程可以知道,我们一次只会跑一流量,最后一层边跑过就不会再悔改,所以说我们只会用到一大片里面的很少的点,所以我们如果可以动态加边的话我 ...
- 【BZOJ 3907】网格 组合数学
大家说他是卡特兰数,其实也不为过,一开始只是用卡特兰数来推这道题,一直没有怼出来,后来发现其实卡特兰数只不过是一种组合数学,我们可以退一步直接用组合数学来解决,这道题运用组合数的思想主要用到补集与几何 ...
- 用PHP迭代器来实现一个斐波纳契数列
斐波纳契数列通常做法是用递归实现,当然还有其它的方法.这里现学现卖,用PHP的迭代器来实现一个斐波纳契数列,几乎没有什么难度,只是把类里的next()方法重写了一次.注释已经写到代码中,也是相当好理解 ...
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D
D. Bear and Two Paths time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- The 13th Zhejiang Provincial Collegiate Programming Contest - C
Defuse the Bomb Time Limit: 2 Seconds Memory Limit: 65536 KB The bomb is about to explode! Plea ...
- POJ2396:Budget(带下界的网络流)
Budget Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8946 Accepted: 3327 Special ...
- 转:增强学习(二)----- 马尔可夫决策过程MDP
1. 马尔可夫模型的几类子模型 大家应该还记得马尔科夫链(Markov Chain),了解机器学习的也都知道隐马尔可夫模型(Hidden Markov Model,HMM).它们具有的一个共同性质就是 ...
- [洛谷P3942] 将军令
洛谷题目链接:将军令 题目背景 历史/落在/赢家/之手 至少/我们/拥有/传说 谁说/败者/无法/不朽 拳头/只能/让人/低头 念头/却能/让人/抬头 抬头/去看/去爱/去追 你心中的梦 题目描述 又 ...
- 【Atcoder】ARC082 E - ConvexScore
[算法]计算几何 [题意]给定平面直角坐标系上的若干个点,任意选点连成凸多边形,凸多边形的价值定义为2^(n-|S|),其中n为凸多边形内部点数(含边界),|S|为顶点数,求总价值.n<=10^ ...