CODEFORCES GYM 2018 USP-ICPC G.Traffic Management、I.I Will Go(Dfs序)

本文解析了两道经典算法题:车辆碰撞时间和竞赛参与者预测。第一题通过从后往前遍历,计算最后一辆撞击发生的时间;第二题利用DFS序预处理图结构,快速判断竞赛参与情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

G. Traffic Management:

在这里插入图片描述在这里插入图片描述
  题意:给n辆车的速度和当前位置,前车撞上后车时速度会变得和后车一样,后车速度不变,问最后一次撞击发生的时间。
  思路:从后往前遍历每一辆车,记录下每一辆车之后的车中的最小速度和此车所在的位置,计算当前车撞上最小速度车的时间,取max即为答案。
  数据范围:1e5
  时间复杂度:O(n)
  反思:同样还是从后往前遍历的思想。在春季选拔赛ICPC南昌网络赛中都有类似思想的题目,但都没有AC。
AC代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5;
const int inf = 0x3f3f3f3f;

int n;

struct NODE{
	int s, v;
	friend bool operator < (NODE a, NODE b){
		return a.s < b.s;
	}
}node[maxn + 5];

struct PP{
	int t, min_v, minv_pos;
}p[maxn + 5];

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d %d", &node[i].s, &node[i].v);
	}
	sort(node + 1, node + 1 + n);//可能不需要sort,但题意没有说明是否是按照位置输入,保险起见
	p[n].min_v = node[n].v;
	p[n].minv_pos = node[n].s;
	float ans = 0;
	for(int i = n - 1; i >= 1; i--){
		if(p[i + 1].min_v >= node[i].v){//如果当前车的速度比之后所有车的速度小或等于最小速度,则永远追不上后车,此时更新最小速度和最小速度位置
			p[i].min_v = node[i].v;
			p[i].minv_pos = node[i].s;
		}
		else {//大于最小速度车则可以追上,此时计算追上时间并取max得到答案
			float dis = p[i + 1].minv_pos - node[i].s;
			float les = node[i].v - p[i + 1].min_v;
			float pos = dis / les;
			ans = max(ans, pos);
			p[i].min_v = p[i + 1].min_v;
			p[i].minv_pos = p[i + 1].minv_pos;
		}
	}
	printf("%.6f\n", ans);
	return 0;
}

I. I Will Go(Dfs序)

在这里插入图片描述
在这里插入图片描述
  题意:给出n个人和q个询问,再给出n个人要舔的对象,对每个询问给出a,b,输出当a去竞赛的时候b去不去竞赛。
  思路:建图,并记录入度,建完图遍历每个人,如果入度为0,则进入dfs,记录dfs序。预处理结束之后对每个询问O(1)查询a,b的L[a],R[a], L[b], R[b],如果L[b] < L[a] && R[b] > R[a],则代表a去的话b一定去。
  涉及算法:DFS序。
  数据范围:2e5
  时间复杂度:nlogn + q
  AC代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1e5;

int n, q;
vector <int> G[maxn + 5];
int l[maxn + 5], r[maxn + 5];
int ind[maxn + 5];
int num;

void dfs(int x){
	l[x] = ++num;
	int len = G[x].size();
	for(int i = 0; i <= len - 1; i++){
		dfs(G[x][i]);
	}
	r[x] = num;
	return;
}
int main(){
	scanf("%d %d", &n, &q);
	for(int i = 0; i <= n - 1; i++){
		int v;
		scanf("%d", &v);
		if(v != -1){
			G[v].push_back(i);
			ind[i]++;
			//printf("---%d %d\n", v, i);
		}
	}
	for(int i = 0; i <= n - 1; i++){
		if(ind[i] == 0){
			dfs(i);
		}
	}
	for(int i = 1; i <= q; i++){
		int a, b;
		scanf("%d %d", &a, &b);
		//printf("%d %d %d %d\n", l[a], r[a], l[b], r[b]);
		if(l[b] <= l[a] && r[b] >= r[a]) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值