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;
}