A - Candy Button
题意
按一次按钮得到一块糖,条件是这次按按钮的时间间隔上次得到糖的时间\(\ge c\)。现在按\(n\)次按钮,已知第\(i\)次按按钮时间为\(t_i\),求得到的糖果数。
思路
模拟。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mxn = 1e6 + 5;
void solve()
{
int n, c, sum = 1;
cin >> n >> c;
vector<int> v(n);
for (int i = 0; i < n; i++)
{
cin >> v[i];
}
int last = v[0];
for (int i = 1; i < n; i++)
{
if (v[i] - last >= c)
{
sum++;
last = v[i];
}
}
cout << sum << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
B - Hands on Ring (Easy)
题意
一个环分成\(n\)块(下标从\(1\)开始),最初左手在\(1\),右手在\(2\)。现在操作\(q\)次,\(h_i\)代表要移动的手,\(t_i\)代表移动到哪。问总移动步数(一次只能移动一步,且两只手不能重叠)。
思路
\(n\)和\(q\)都很小,直接暴力模拟。注意取余操作会出现\(0\),所以把下标统一减一处理。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n, q;
cin >> n >> q;
int l = 0, r = 1, ans = 0;
for (int i = 0; i < q; i++)
{
char h;
int t;
cin >> h >> t;
t--;
bool f = false;
if (h == 'L')
{
int j = l;
while (j != t)
{
j = (j + 1) % n;
if (j == r)
{
f = true;
}
}
ans += ((f ? l - t : t - l) + n) % n;
l = t;
}
else
{
int j = r;
while (j != t)
{
j = (j + 1) % n;
if (j == l)
{
f = true;
}
}
ans += ((f ? r - t : t - r) + n) % n;
r = t;
}
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
C - Prepare Another Box
题意
\(n\)个玩具,大小为\(a_i\);\(n-1\)个盒子,大小为\(b_i\)。现在加一个尽量小的盒子使得所有玩具都能被装进盒子。
思路
因为只能加一个盒子,所以除去加的盒子外还有装不下的就无解;否则升序排序后第一个装不下的就是答案。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n;
cin >> n;
vector<int> a(n), b(n - 1);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n - 1; i++)
{
cin >> b[i];
}
sort(a.begin(), a.end(), greater<int>());
sort(b.begin(), b.end(), greater<int>());
int i = 0;
while (i < n - 1 && b[i] >= a[i]) // 找第一个装不下的
{
i++;
}
for (int j = i; j < n - 1; j++)
{
if (b[j] < a[j + 1]) // 除了加的盒子还有装不下的
{
cout << -1 << endl;
return;
}
}
cout << a[i] << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
D - Cycle
题意
给定\(n\)个点的简单连通无向图(编号从\(1\)开始)。求包含顶点\(1\)的最小环大小。
思路
等价于从\(1\)到\(1\)的最短路。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mxn = 1e6 + 5;
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<int>> g(n + 1, vector<int>());
for (int i = 0; i < m; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
}
int ans = LLONG_MAX;
vector<int> dis(n + 1, -1);
queue<int> q;
dis[1] = 0;
q.push(1);
while (q.size())
{
int u = q.front();
q.pop();
for (auto& v : g[u])
{
if (v == 1)
{
ans = min(ans, dis[u] + 1);
}
if (dis[v] == -1)
{
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
if (ans == LLONG_MAX)
{
cout << -1 << endl;
return;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
E - Max × Sum
题意
给定两个长度为\(n\)的序列\(A\)、\(B\),令\(S\)为\(\{ 1,2,···,n \}\)的子序列,长度为\(k\)。求 \(\max A_{i \in S}\ ×\ \sum B_{i \in S}\) 的最小值。
思路
枚举\(\max A_{i \in S}\),再用堆维护\(B\)的前\(K\)小即可。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node
{
int a, b;
bool operator < (const node& x) const
{
if (x.a == a)
{
return b < x.b;
}
return a < x.a;
}
};
void solve()
{
int n, k;
cin >> n >> k;
vector<node> v(n);
for (int i = 0; i < n; i++)
{
cin >> v[i].a;
}
for (int i = 0; i < n; i++)
{
cin >> v[i].b;
}
sort(v.begin(), v.end());
int ans = LLONG_MAX, sum = 0;
priority_queue<int> q;
for (int i = 0; i < k; i++)
{
q.push(v[i].b);
sum += v[i].b;
}
ans = min(ans, sum * v[k - 1].a);
for (int i = k; i < n; i++) // 枚举 max a[i],维护b的前k小
{
int now = q.top();
ans = min(ans, v[i].a * (sum - now + v[i].b));
q.push(v[i].b);
sum += v[i].b;
now = q.top();
q.pop();
sum -= now;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}