Codeforces Round #787 (Div. 3) A - F 題解
阿新 • • 發佈:2022-05-06
A. Food for Animals
直接找一下本身夠不夠,然後不夠再拿 c
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <string> #include <queue> #include <functional> #include <map> #include <set> #include <cmath> #include <cstring> #include <deque> #include <stack> using namespace std; typedef long long ll; #define pii pair<int, int> const ll maxn = 2e5 + 10; const ll inf = 1e17 + 10; int main() { int t; cin >> t; while(t--) { int a, b, c, d, e; cin >> a >> b >> c >> d >> e; d -= min(d, a); e -= min(b, e); if(c >= d + e) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
B. Make It Increasing
因為只能往下除,直接從後往前找就行
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <string> #include <queue> #include <functional> #include <map> #include <set> #include <cmath> #include <cstring> #include <deque> #include <stack> using namespace std; typedef long long ll; #define pii pair<int, int> const ll maxn = 2e5 + 10; const ll inf = 1e17 + 10; ll num[maxn], pre[maxn]; int main() { int t; scanf("%d", &t); ll len = 1ll << 33; while(t--) { int n; scanf("%d", &n); for(int i=0; i<n; i++) scanf("%lld", &num[i]); int ans = 0; ll pre = num[n-1] + 1; int f = 1; for(int i=n-1; i>=0 && f; i--) { while(f && num[i] >= pre) { if(num[i] == 0) f = 0; ans++; num[i] >>= 1; } pre = num[i]; } printf("%d\n", f ? ans : -1); } return 0; }
C. Detective Task
思維題,說謊的人一定是在轉折處,也就是最後一個出現的 1 和最早出現的 0 之間
直接雙指標判斷一下這個區間有多少個人就行
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <string> #include <queue> #include <functional> #include <map> #include <set> #include <cmath> #include <cstring> #include <deque> #include <stack> using namespace std; typedef long long ll; #define pii pair<int, int> const ll maxn = 2e5 + 10; const ll inf = 1e17 + 10; ll num[maxn], pre[maxn]; int main() { int t; cin >> t; while(t--) { string s; cin >> s; int l = 0, r = s.length() - 1, len = s.length(); while(l < len && s[l] != '0') l++; while(r >= 0 && s[r] != '1') r--; int ans = 0; ans = l - r + 1; if(r == -1) ans--; if(l == len) ans--; cout << ans << endl; } return 0; }
D. Vertical Paths
這個題直接找路徑就行,從葉子結點往上找比較方便
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
int top[maxn], vis[maxn], du[maxn];
stack<int>st[maxn];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
for(int i=0; i<=n; i++) du[i] = vis[i] = 0;
for(int i=1; i<=n; i++)
{
scanf("%d", &top[i]);
if(i == top[i]) top[i] = 0;
du[top[i]]++;
}
int tp = 0;
for(int i=1; i<=n; i++)
{
if(du[i]) continue;
int now = i;
while(now && vis[now] == 0)
{
st[tp].push(now);
vis[now]++;
now = top[now];
}
tp++;
}
printf("%d\n", tp);
for(int i=0; i<tp; i++)
{
printf("%d\n", st[i].size());
while(st[i].size())
{
int now = st[i].top();
st[i].pop();
printf("%d ", now);
}
printf("\n");
}
tp = 0;
printf("\n");
}
return 0;
}
E. Replace With the Previous, Minimize
類似於記憶化搜尋
由於是字典序從小到大,因此從左到右開始找字母,看看能不能壓到 a 去,然後記憶一下被壓過的每種字母
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 310;
const ll inf = 1e17 + 10;
int alp[maxn];
int main()
{
int t;
cin >> t;
while(t--)
{
int n, k;
cin >> n >> k;
string s;
cin >> s;
if(k >= 26)
{
while(n--) cout << 'a';
cout << endl;
continue;
}
int len = s.length();
for(int i=0; i<300; i++) alp[i] = 0;
alp['a'] = 'a';
for(int i=0; i<len && k; i++)
{
if(alp[s[i]]) continue;
int now = s[i];
while(alp[now] == 0) now--;
int way = s[i] - now;
if(k < way) way = k, now = s[i] - k;
k -= way;
way = alp[now] ? alp[now] : now;
for(int j=now+1; j<=s[i]; j++) alp[j] = way;
}
for(int i=0; i<n; i++)
s[i] = alp[s[i]] ? alp[s[i]] : s[i];
cout << s << endl;
}
return 0;
}
F. Vlad and Unfinished Business
如果想要在一個樹上,要求從根出發,經過若干個點的話,最後回到根,基本想法就是從要經過的點往根遍歷,沒經過一條邊,就要代價 +2,因為一次是往下,第二次是經過了該子樹要經過的點,然後回去
所以這題就套用這個想法,把 y 也作為要經過的點,然後再減去 x 到 y 的距離,就變成最後是在 y 點停下
這題和天梯賽的 L2-3 一模一樣的想法,出題人可能打過天梯賽?
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const int maxn = 2e5 + 10;
int w[maxn], dis[maxn], top[maxn], vis[maxn];
vector<int>gra[maxn];
void bfs(int s)
{
queue<pii>q;
q.push(make_pair(s, 0));
top[s] = s;
while(q.size())
{
pii now = q.front();
q.pop();
int u = now.first;
dis[u] = now.second;
for(int i=0; i<gra[u].size(); i++)
{
int v = gra[u][i];
if(top[v]) continue;
top[v] = u;
q.push(make_pair(v, now.second + 1));
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n, m, x, y;
scanf("%d%d%d%d", &n, &m, &x, &y);
for(int i=0; i<m; i++) scanf("%d", &w[i]);
w[m++] = y;
for(int i=1; i<n; i++)
{
int a, b;
scanf("%d%d", &a, &b);
gra[a].push_back(b);
gra[b].push_back(a);
}
bfs(x);
int ans = 0;
vis[x] = 1;
for(int i=0; i<m; i++)
{
int now = w[i];
while(vis[now] == 0)
{
vis[now] = 1;
ans += 2;
now = top[now];
}
}
ans -= dis[y];
printf("%d\n", ans);
for(int i=0; i<=n; i++)
{
vis[i] = top[i] = 0;
gra[i].clear();
}
}
return 0;
}
G. Sorting Pancakes
群友說是個三維 dp? 不懂