G-Horse Drinks Water_2024牛客暑期多校训练营4 (nowcoder.com)
G:
经典的将军饮马的问题。
解决思路:
将马的坐标分别对x轴对称以及对y轴对称,这两者到t的坐标的距离取最小值即可。
#include <bits/stdc++.h>
using namespace std;
double dist(double xg, double yg, double xt,double yt){
return sqrt((xg - xt)*(xg - xt) + (yg - yt) * (yg - yt));
}
int main() {
int t; cin >> t;
while(t--){
double xg,yg,xt,yt; cin >> xg >> yg >> xt >> yt;
printf("%.10lf\n",min(dist(-xg,yg,xt,yt),dist(xg,-yg,xt,yt)));
}
return 0;
}
I-Friends_2024牛客暑期多校训练营4 (nowcoder.com)
I:
题目解释:
有 n 个人站成一排,从左到右编号为 1 到 n。这些人中有 m 对朋友。 定义区间 [l, r] 为友好区间,当且仅当该区间内的每一对人都是朋友。 也就是说,在区间 [l, r] 内,如果所有可能的两两组合都是朋友关系,那么这个区间就是一个友好区间。 题目要求你计算并输出这样的友好区间的数量。 输入格式 第一行包含两个整数 n 和 m,表示人数和朋友对数。 n 的范围是 1 到 1000000 m 的范围是 1 到 1000000 接下来的 m 行每行包含两个整数 u 和 v,表示一对朋友。 1 ≤ u < v ≤ n 保证输入中没有重复的朋友对。
输出格式:输出一个整数,表示友好区间的数量。(朋友关系不具有传递性;长度为1的区间是友好区间)。
解决思路:
对友好区间的解释:对于一个区间l,r要是一个友好区间当且仅当区间里面的人彼此之间都是好朋友。不难发现,对于一个区间[l,r]如果是一个好区间,那么[l,k],[k+1,r]也是好区间,那么我们就可以对于每一个人固定左端点,去寻找最大的右端点。以这个人为左端点的好区间数量为j-i+1个
集合里面有一个find函数。时间复杂度为 O(log n),远优于 vector
的线性搜索,所以此代码采用set集合来表示每一个人的朋友集合。
a[p].find(i)
:这个方法尝试在集合 a[p]
中找到元素 i
。如果元素 i
存在于集合中,它将返回一个指向该元素的有效迭代器;如果不存在,则返回一个特殊的迭代器,称为 end
迭代器。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N=1000005;
int n,m;
set<int>a[N];
ll s;
//判断是否是合法的右端点
bool MaxRight(int friends,int l,int r)
{
if(a[friends].size() < r - l + 1) return false;
for(int i = l;i <= r; i++){
if(a[friends].find(i) == a[friends].end()) return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> n >> m;
for(int i = 0; i < m; i++){
int u,v; cin >> u >>v;
a[u].insert(v);
a[v].insert(u);
}
for(int i = 1,j = 1; i <= n; i++){
while(j < i) j ++;
while(i < n && MaxRight(j+1,i,j)) j++;
//对于每一个人的友好区间都累加到s里面
s += j - i + 1;
}
cout << s <<'\n';
return 0;
}