2024牛客寒假算法基础集训营5
A
void solve()
{
int n;
cin >> n;
int cnt = 0;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
if (x == 1)
cnt++;
}
cout << n - cnt << endl;
}
B
答案可能是
m_y_g_o
ll f[N][N][N];
void solve()
{
string s;
cin >> s;
int n = s.size();
s = '#' + s;
vector<ll> f(n + 10, 0);
f[0] = 1, f[1] = 2, f[2] = 3, f[3] = 5;
for (int i = 4; i <= n; i++)
f[i] = (f[i - 1] + f[i - 2]) % mod;
ll ans = 0;
for (int i = 4; i <= n; i++)
if (s[i] == 'o')
for (int j = i - 1; j >= max(1, i - 2); j--)
if (s[j] == 'g')
for (int k = j - 1; k >= max(1, j - 2); k--)
if (s[k] == 'y')
for (int l = k - 1; l >= max(1, k - 2); l--)
if (s[l] == 'm')
{
// cout << l << " " << k << " " << j << " " << l << endl;
ans = (ans + f[l - 1] * f[n - i] % mod) % mod;
}
cout << ans << endl;
}
C
每次放一个0,都会使得两边数-1
void solve()
{
ll n, ans = 0;
cin >> n;
vector<ll> a(n + 2, 0);
a[0] = 1e10, a[n + 1] = 1e10;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n + 1; i++)
{
ll sub = min(a[i] - 1, a[i - 1] - 1);
ans += sub;
a[i] -= sub;
}
cout<<ans<<endl;
}
D
E
偶数一定可以
奇数贪心,使得每个偶数位置a[i]尽可能大且满足\(a[i]\le a[i+1]\)
检查是否满足即可
void solve()
{
int n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
if (n % 2 == 0)
{
cout << "YES" << endl;
return;
}
else
{
ll tot = 0;
for (int i = n - 1; i >= 1; i -= 2)
{
a[i] += tot * i;
a[i - 1] += tot * (i - 1);
if (a[i] > a[i + 1])
{
cout << "NO" << endl;
return;
}
ll cnt = (a[i + 1] - a[i]) / i;
tot += cnt;
a[i] += cnt * i, a[i - 1] += cnt * (i - 1);
if (a[i - 1] > a[i])
{
cout << "NO" << endl;
return;
}
}
cout << "YES" << endl;
}
}
F
偶数就是\(a[i-1]-a[i]\)差值最大的,只需要操作n位置即可
奇数重复e的贪心过程,每次变大的时候与\(a[i-1]-a[i]\)的max取min即可
void solve()
{
int n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
ll mx = 0, ans = 0;
for (int i = 2; i <= n; i++)
mx = max(mx, a[i - 1] - a[i]);
ans = mx;
if (n % 2)
{
ans = 0;
ll tot = 0;
for (int i = n - 1; i >= 1; i -= 2)
{
a[i] += tot * i;
a[i - 1] += tot * (i - 1);
if (a[i] > a[i + 1])
{
cout << "-1" << endl;
return;
}
ll cnt = min((a[i + 1] - a[i]) / i, mx);
mx -= cnt, ans += cnt;
tot += cnt;
a[i] += cnt * i, a[i - 1] += cnt * (i - 1);
if (a[i - 1] > a[i])
{
cout << "-1" << endl;
return;
}
}
}
cout << ans << endl;
}
G/H
暴力打表发现存在一个递增的p[i]+i,并且是将1,2,3,4...分割成若干段后反转得到的,暴力枚举即可
void solve()
{
vector<int> pr;
vector<bool> not_pr(N);
auto getpr = [&](int n)
{
for (int i = 2; i <= n; ++i)
{
if (!not_pr[i])
pr.push_back(i);
for (int p : pr)
{
if (i * p > n)
break;
not_pr[i * p] = true;
if (i % p == 0) // 说明i*p已经被一个更小的i判断过了
break;
}
}
};
getpr(2e6);
int n;
cin >> n;
vector<int> ans(n + 1);
for (int i = 1; i <= n; i++)
ans[i] = i;
int r = n;
for (int i = n; i >= 1; i--)
{
if (!not_pr[i + r])
{
for (int j = r, k = i; j >= k; j--, k++)
swap(ans[j], ans[k]);
r = i - 1;
}
}
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
I
分类讨论
void solve()
{
ll t, a, k;
cin >> t >> a >> k;
ll l = 0, r = t;
if (l > r)
swap(l, r);
l -= k, r += k;
if (a >= l && a <= r)
cout << abs(a) + abs(t - a) << endl;
else
cout << abs(t) + 2 * abs(t - a) << endl;
}
J
三分:
void solve()
{
ll n;
cin >> n;
vector<pll> seg(n);
for (auto &[l, r] : seg)
cin >> l >> r;
auto f = [&](int x) -> ll
{
ll res = 0;
for (int i = 0; i < n; i++)
if (x < seg[i].x)
res += seg[i].x - x, x = seg[i].x;
else if (x > seg[i].y)
res += x - seg[i].y, x = seg[i].y;
return res;
};
int l = seg[0].x, r = seg[0].y;
for(int i=0;i<=60;i++)
{
int lmid = l + (r - l) / 3;
int rmid = r - (r - l) / 3;
if (f(lmid) < f(rmid))
r = rmid;
else
l = lmid;
}
ll ans = 1e18;
for (int i = l; i <= r; i++)
ans = min(ans, f(i));
cout << ans << endl;
}
贪心:
void solve()
{
int n, l, r;
cin >> n;
cin >> l >> r;
ll ans = 0;
for (int i = 1; i < n; i++)
{
int x, y;
cin >> x >> y;
if (x > r)
{
ans += x - r;
l = r = x;
}
else if (y < l)
{
ans += l - y;
l = r = y;
}
else
{
l = max(l, x), r = min(r, y);
}
}
cout << ans << endl;
}
K
类似完全背包
void solve()
{
ll n, p;
cin >> n >> p;
vector<ll> f(n + 1, 1e10);
f[0] = 0;
for (int i = 1; i <= n; i++)
{
ll a, b;
cin >> a >> b;
b = min(b, n - 1);
for (int i = 0; i < n; i++)
f[i] = min(f[i], f[max(0ll, i - b)] + a);
}
ll ans = 1e10;
for (int i = 0; i < n; i++)
ans = min(ans, f[i] + (n - i) * p);
cout << ans << endl;
}
L
void solve()
{
int n, x;
cin >> n >> x;
for (int i = 0; i <= n ; i++)
{
if (n - (2 * i )== x)
{
cout << n - i << " " << i << endl;
return;
}
}
cout << "-1" << endl;
}
M
分类讨论
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
cin >> b[i];
if (n == 1)
cout << "-1" << endl;
else if (n == 2)
{
for (int i = 1; i <= n; i++)
if (a[i] == b[i])
{
cout << "-1" << endl;
return;
}
cout << "1" << endl;
}
else
{
if (a[1] == b[2] || a[n] == b[n - 1])
{
cout << "1" << endl;
return;
}
for (int i = 2; i <= n - 1; i++)
{
for (int j = i - 1; j <= i + 1; j++)
if (a[i] == b[j])
{
cout << "1" << endl;
return;
}
}
cout << "2" << endl;
}
}