EOJ Monthly 2021.1
2/6
2021快乐,期末考加油——
B想通了比C简单
C思路没问题但是不知道为什么一直WA19
B - 洪水
B. 洪水 - EOJ Monthly 2021.1 Sponsored by TuSimple - ECNU Online Judge
刚开始的想法是二分+bfs(必T啊
然后还不信邪冲了一发,T1
有点cf思维题的感觉
其实数据范围给的很清楚的是思维题
官方题解 : 考虑终点 (c,d) 未被淹没的最晚时刻 T。我们可以证明,以 (a,b) 为起点的最晚出发时刻是 T−|a−c|−|b−d|。换句话说, Cuber 出现后可以沿着最短路径不停地走,并且到达终点后的下一时刻终点被淹没。
为什么一定可行呢?考虑 t 时刻 Cuber 站在 (x,y) 的情况。因为此时 (x,y) 未被淹没,所以在 t−1 时刻 (x,y) 的相邻格子也未被淹没(如果某相邻格子在 t−1 时刻被淹没,那么 (x,y) 必会在 t 时刻被淹没,故矛盾)。所以,如果 “时光倒流”,Cuber 就能自由移动,我们就能轻易推得上述结论了。
时间复杂度 O(nq),可优化到 O((n+q)logn)。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct node {
int t, x, y;
}mp[maxn];
int main() {
int n, q;
cin >> n >> q;
for(int i = 1; i <= n; ++ i) {
cin >> mp[i].t >> mp[i].x >> mp[i].y;
}
while(q--) {
int a, b, c, d;
cin >> a >> b >> c >> d;
int mn = 1e9;
for(int i = 1; i <= n; ++i) {
mn = min(mn, mp[i].t + abs(c - mp[i].x) + abs(d - mp[i].y));
}
cout << mn - abs(a - c) - abs(b - d) - 1 << endl;
}
}
C - 魔树
C. 魔树 - EOJ Monthly 2021.1 Sponsored by TuSimple - ECNU Online Judge
疯狂wa19,不肯重构,赛后看到题解思路没问题,先放一放8
看到提交里有个代码感觉写的很清楚:
#include <bits/stdc++.h>
using namespace std;
long long MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
vector<int> edge[maxn];
int m,n,p=0;
// p:总层数
int leaves[maxn];
vector<long long> ans;
int DFS(int root,int g){
int ans=0;
for(int i=0;i<edge[root].size();i++){
int current = edge[root][i];
if(current==g)continue;
int c=DFS(current,root);
ans = ans>c+1?ans:c+1;
}
p=p>ans?p:ans;
leaves[ans]++;
return ans; // 返回该节点所在的层数
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)edge[i].clear();
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
edge[a].push_back(b);
edge[b].push_back(a);
}
for(int i=0;i<n;i++)leaves[i]=0;
DFS(1,-1);
for(int i=p;i>=0;i--){
ans.push_back(leaves[i]);
}
for(int i = 0;i<m;i++){
int t;
char f='c';
while(f!='A'&&f!='D')scanf("%c",&f);
if(f=='A'){
scanf("%d",&t);
ans.push_back(ans.back()*t%MOD);
}else{
ans.pop_back();
}
}
int res=0;
for(int i=0;i<ans.size();i++){
res+=ans[i];
res%=MOD;
}
printf("%d\n",res);
}