L1 - L2题解链接:https://blog.csdn.net/mldl_/article/details/114991298
7-13 是否完全二叉搜索树 (30分)
思路
二叉树常规操作,根据要求构造二叉树,BFS判断是否为满二叉树即可。
ACcode
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 5;
int t[maxn], a[maxn];
vector<int> res;
queue<int> qu;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
memset(t, -1, sizeof(t));
for(int i = 1; i <= n; i++){
int pos = 1;
while(1){
if(t[pos] == -1){
t[pos] = a[i];
break;
}
else if(a[i] > t[pos]) pos = pos * 2;
else pos = pos * 2 + 1;
}
}
int flag = 1;
for(int i = 1; i <= n; i++) if(t[i] == -1) flag = 0;
qu.push(1);
while(!qu.empty()){
int now = qu.front(); qu.pop();
res.push_back(t[now]);
if(t[now*2] != -1) qu.push(now*2);
if(t[now*2+1] != -1) qu.push(now*2+1);
}
if(flag) cout << "YES" << endl;
else cout << "NO" << endl;
for(int i = 0; i < n; i++) cout << (i == 0 ? "" : " ") << res[i];
return 0;
}
7-14 直捣黄龙 (30分)
思路
dijkstra 跑最短路(堆优化,写结构体自定义排序维护题目信息),定义 pre 数组记录前导点回归路径和计数数组统计路径数即可。
ACcode
#include <bits/stdc++.h>
#define PI acos(-1)
#define ld long double
#define IOS cin.tie(0), ios::sync_with_stdio(false)
#define ll long long
#define endl "\n"
const double eps = 1e-8;
const ll INF = 0x3f3f3f3f;
const ll mod = 998244353;
const int maxn = 1e6 + 5;
using namespace std;
typedef struct Node{
ll id;
ll dis, cnt, w;
} node;
bool operator < (node A, node B){
if(A.dis == B.dis){
if(A.cnt == B.cnt) return A.w < B.w;
return A.cnt < B.cnt;
}
return A.dis > B.dis;
}
map<string, int> id;
map<int, string> name;
vector<pair<ll, ll> > ma[300];
ll w[300], pre[300];
ll dis[300], cnt[300], val[300], sum[300];
priority_queue<node> qu;
void path(int x){
if(pre[x] == -1){
cout << name[x];
return;
}
path(pre[x]);
cout << "->" << name[x];
}
int main(){
IOS;
int n, m; string a, b;
cin >> n >> m >> a >> b;
id[a] = 1; name[1] = a;
string s; int x;
for(int i = 2; i <= n; i++){
cin >> s >> x;
id[s] = i; name[i] = s;
w[i] = x;
}
int S = id[a], E = id[b];
for(int i = 1; i <= m; i++){
cin >> a >> b >> x;
int u = id[a], v = id[b];
ma[u].push_back({v, x});
ma[v].push_back({u, x});
}
for(int i = 1; i <= n; i++) dis[i] = 1e18, cnt[i] = val[i] = -1e18, sum[i] = 0;
pre[S] = -1; dis[S] = cnt[S] = val[S] = 0; sum[S] = 1;
qu.push({S, 0, 0, 0});
node now, next;
while(!qu.empty()){
now = qu.top(); qu.pop();
for(auto u : ma[now.id]){
next.id = u.first;
next.dis = now.dis + u.second;
next.cnt = now.cnt + 1;
next.w = now.w + w[next.id];
if(next.dis < dis[next.id]){
dis[next.id] = next.dis;
cnt[next.id] = next.cnt;
val[next.id] = next.w;
sum[next.id] = sum[now.id];
pre[next.id] = now.id;
qu.push(next);
}
else if(next.dis == dis[next.id]){
sum[next.id] += sum[now.id];
if(next.cnt > cnt[next.id]){
cnt[next.id] = next.cnt;
val[next.id] = next.w;
pre[next.id] = now.id;
qu.push(next);
}
else if(next.cnt == cnt[next.id]){
if(next.w > val[next.id]){
val[next.id] = next.w;
pre[next.id] = now.id;
qu.push(next);
}
}
}
}
ma[now.id].clear();
}
path(E); cout << endl;
cout << sum[E] << " " << dis[E] << " " << val[E] << endl;
return 0;
}
7-15 水果忍者 (30分)
思路
思维题。
题目保证有解,一定存在一条直线通过两条线段端点(一个上端点一个下端点),
O
(
n
2
)
O(n^2)
O(n2) 判断即可。
Accode
#include <bits/stdc++.h>
#define ll long long
using namespace std;
typedef struct Node{
int x;
int y1, y2;
} node;
node a[1005];
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i].x >> a[i].y1 >> a[i].y2;
for(int i = 1; i <= n; i++){
pair<ll, ll> k1 = {3e6, 1}, k2 = {-3e6, 1}; int res = -1;
for(int j = 1; j <= n; j++){
if(i == j) continue;
ll y = a[j].y1 - a[i].y2; // 上
ll x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
if(y * k1.second < k1.first * x) k1 = {y, x}, res = j;
y = a[j].y2 - a[i].y2; // 下
x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
if(y * k2.second > k2.first * x) k2 = {y, x};
}
if(k1.first * k2.second >= k2.first * k1.second){
cout << a[i].x << " " << a[i].y2 << " " << a[res].x << " " << a[res].y1;
break;
}
k1 = {3e6, 1}, k2 = {-3e6, 1}; res = -1;
for(int j = 1; j <= n; j++){
if(i == j) continue;
ll y = a[j].y1 - a[i].y1; // 上
ll x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
if(y * k1.second < k1.first * x) k1 = {y, x}, res = j;
y = a[j].y2 - a[i].y1; // 下
x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
if(y * k2.second > k2.first * x) k2 = {y, x};
}
if(k1.first * k2.second >= k2.first * k1.second){
cout << a[i].x << " " << a[i].y1 << " " << a[res].x << " " << a[res].y1;
break;
}
}
return 0;
}