ICPC 2019-2020 North-Western Russia Regional Contest train 補題記錄
阿新 • • 發佈:2021-11-08
A.溫暖的簽到
E. Equidistant
題目大意:給定一顆n節點的樹,給定幾個點,問我們是否能夠在樹上找到一點到這幾個點的距離是一樣的
解題思路:我們把這幾個點同時放進去並且進行BFS操作,並且我們開一個數組去記錄有幾個最終結點到這裡的最短路徑的的條數,因此對於每個經過的結點,我們若有dis[x] == dis[h] + 1,則cnt[x] += cnt[h],如果dis[x] > dis[h] + 1,則cnt[x] = cnt[h]
#include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; const int inf = 0x3f3f3f3f; vector<int> G[maxn]; queue<int> q; int cnt[maxn]; int dis[maxn]; int n,m; void BFS() { while(!q.empty()) { int x = q.front(); q.pop(); for(int f : G[x]) { if(dis[f] == dis[x] + 1) cnt[f] += cnt[x]; else if(dis[f] > dis[x] + 1) { dis[f] = dis[x] + 1; cnt[f] = cnt[x]; q.push(f); } } } } void solve() { scanf("%d %d",&n,&m); memset(dis,inf,sizeof dis); for(int i = 1;i <= n - 1;++i) { int u,v; scanf("%d %d",&u,&v); G[u].emplace_back(v); G[v].emplace_back(u); } int pos; for(int i = 1;i <= m;++i) { scanf("%d",&pos); dis[pos] = 0; cnt[pos] = 1; q.push(pos); } //cout << "??"<<"\n"; BFS(); for(int i = 1;i <= n;++i) { //cout<<i<<" "<< cnt[i] <<"\n"; if(cnt[i] == m) { printf("YES\n%d\n",i); return; } } printf("NO\n"); } int main() { solve(); return 0; }
I-Ideal Pyramid
題目大意:給定三維空間中的n個點,找出一個最小四稜錐能夠將這些點全部包含在錐體裡面,並且輸出相應頂點的座標
題目分析:由於這道題目求的是最小的高度,那麼我們可以知道必定會存在一根柱子會與金字塔的面相切,那麼對於金子塔上面的任意一個點(非頂點)(xi,yi,zi),和其頂點(x,y,z),對於x來說可以列出這樣的式子
,那麼對於這個絕對值我們也可以進行一個拆分,讓式子後面大於等於0,即可獲得x的左右邊界,同時用這種方法也可以獲得y的左右邊界,那麼最後的點,我們可以知道是(xl + xr >> 1,yl + yr >> 1),對於高度來說,高度是需要取x和y之中長度相對來說比較長的那一根,因此我們也可以輸出最後的結果了#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; typedef long long ll; const ll inf = 0x3f3f3f3f3f3f3f3f; ll xr = - inf,xl = inf,yr = - inf,yl = inf; ll x,y,h; int n; int main() { scanf("%d",&n); for(int i = 1;i <= n;++i) { scanf("%lld %lld %lld",&x,&y,&h); xr = max(h + x,xr); xl = min(x - h,xl); yr = max(h + y,yr); yl = min(y - h,yl); } printf("%lld %lld %lld\n",(xr + xl) >> 1,(yl + yr) >> 1,max((xr - xl + 1),(yr - yl + 1)) >> 1); return 0; }
M-Managing Difficulties
題目大意:找到一個序列滿足aj - ai = ak - aj
解題思路:先分析資料範圍2000,那麼n^2的時間複雜度是肯定可以被接受的,那麼我們可以先把前面的 2 aj - ai給算出來,最後再去讀入進來ak的時候將答案給計算進去(注意使用unordered_map,還有在使用count的時候時間複雜度會比直接查詢要來的小)
#include <bits/stdc++.h>
using namespace std;
int T,n;
long long ans;
const int maxn = 2e3 + 10;
int a[maxn];
unordered_map<int,int> mp;
int tmp;
void solve()
{
scanf("%d",&n);
ans = 0;
mp.clear();
for(int i = 1;i <= n;++i)
{
scanf("%d",&a[i]);
if(mp.count(a[i]) != 0) ans += mp[a[i]];
for(int j = 1;j < i;++j)
{
mp[2 * a[i] - a[j]]++;
}
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
J-Just the Last Digit
題目大意:給定一張圖,aij代表從i到j的路有aij % 10條
解題思路:分析資料範圍,資料範圍比較小,那麼我們可以直接通過列舉中間那個來判斷相對應的路是否符合我們的要求
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e2 + 10;
int mp[maxn][maxn];
char str[maxn][maxn];
int ans[maxn][maxn];
int n;
void solve()
{
scanf("%d",&n);
//getchar();
for(int i = 1;i <= n;++i)
{
scanf("%s",str[i] + 1);
// printf("%s\n",str[i] + 1);
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
//printf("str: %s",str[i]);
mp[i][j] = str[i][j] - '0';
}
}
// for(int i = 1;i <= n;++i)
// {
// for(int j = 1;j <= n;++j)
// {
// printf("%d ",mp[i][j]);
// }
// printf("\n");
// }
for(int k = 1;k <= n;++k)
{
for(int i = 1;i <= n - k;i++)
{
int f = i + k,cnt = 0;
for(int j = i + 1;j < f;++j)
{
cnt = (cnt + ans[i][j] * mp[j][f]) % 10;
}
if(cnt != mp[i][f]) ans[i][f] = 1;
}
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
printf("%d",ans[i][j]);
}
printf("\n");
}
}
int main()
{
solve();
return 0;
}