23/8/22 比赛总结
预估分数 100 实际分数 160
解题过程
- B
- A
- D
B 题:一眼丁真最短路。然后发现边数有限制,长得是棵树?然后就 dijkstra
不太对吧?再一想,边权为 1 干嘛不用 dfs
?一小会就过了
A 题:看起来懵懵的,然后发现,可以一次枚举两个不同种类的牛,然后如果有牛给拦住了,就更新答案,至于最后为什么没有 AC 呢?那就是我个 SB 把用来排序的 cmp
函数写错了!!!
D 题:与 A 题差不多,就是在发现有牛挡住了其他牛的时候,把 A 题拿来存答案的数组当做标记数组,在另外开个变长数组去存下这个牛挡住了哪个牛。输出答案的时候不仅要把自己挡住的牛的个数加上,还要加上自己挡住的牛的个数和自己挡住的牛的挡住的牛挡住的牛挡住的牛...的个数(这不背锅的吗?)
以下展示关键代码:
A 题:
//两个排序用的cmp
bool cmp1(rs7 x, rs7 y)
{
return x.x < y.x;
}
bool cmp2(rs7 x, rs7 y)
{
return x.y < y.y;
}
---------------------------
//对于每两个不一样种类的牛的操作(Audi_RS7是答案数组)
if (Audi_RS7[b[j].p] != inf || Audi_RS7[a[i].p] != inf) continue;
if (a[i].x > b[j].x && a[i].y < b[j].y)
{
int t1 = b[j].y - a[i].y, t2 = a[i].x - b[j].x;
if (t1 < t2) Audi_RS7[b[j].p] = min(Audi_RS7[b[j].p], t2);
if (t1 > t2) Audi_RS7[a[i].p] = min(Audi_RS7[a[i].p], t1);
}
B 题:
void dfs(int u)
{
st[u] = true;
int cnt = 1, s = 1;
for (int v : g[u])
{
if (st[v] == false)
{
cnt ++ ;
ans ++ ;
dfs(v);
}
}
while (s < cnt) s *= 2, ++ ans;
}
D 题:
//g 数组是存自己挡住了哪些牛的路
int dfs(int u)
{
int cnt = 0;
for (int v : g[u])
{
cnt += 1 + dfs(v);
}
return cnt;
}
现在来分析 C 题
首先,对输入进来的数据先对 x
轴再对 y
轴排序
然后枚举每两个牛,记录下他们的上下的 x
轴,在依次枚举 y
轴,用公式记录下答案。注意!空集也算一种!
代码展示:
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int N = 2505;
int n, ans = 1;
int l[N], r[N];
struct node
{
int x, y;
bool operator < (const node& t)
{
return x != t.x ? x < t.x : y < t.y;
}
} a[N];
signed main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; i ++ ) scanf("%lld%lld", &a[i].x, &a[i].y);
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++ )
{
int lt = 0, rt = 0;
ans += 1;
for (int j = i - 1; j >= 1; j -- )
{
if (a[i].y > a[j].y)
{
ans += (rt + 1) * (l[j] + 1);
r[j] ++ ;
lt ++ ;
}
else
{
ans += (lt + 1) * (r[j] + 1);
l[j] ++ ;
rt ++ ;
}
}
}
printf("%lld\n", ans);
return 0;
}