CodeForces Gym 101623 간략한 문제 해결
Ascending Photo
먼저 이산화하고 인접한 동일한 수를 하나로 만든다.값 영역을 작은 DP에서 큰 DP로 고려하면 i와 i+1i+1 사이가 절개되지 않으면 i+1i+1과 i+2i+2 사이가 절개되어야 하기 때문에 DP 값과 지난번 결정 지점만 유지하면 됩니다.최대치와 차대치만 유지하면 이동할 수 있다는 것을 발견하기 어렵지 않다.
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
vector<int> a(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
vector<int> disc = a;
sort(disc.begin(), disc.end());
disc.erase(unique(disc.begin(), disc.end()), disc.end());
vector<vector<int>> all(disc.size() + 1);
vector<int> b;
for (int i = 0; i < n; ++i) {
a[i] = lower_bound(disc.begin(), disc.end(), a[i]) - disc.begin();
if (!b.empty() && a[i] == b.back()) {
continue;
}
all[a[i]].push_back(b.size());
b.push_back(a[i]);
}
n = b.size();
pair<int, int> u = make_pair(0, n), v = make_pair(0, n);
for (int i = 0; i < disc.size(); ++i) {
pair<int, int> x = make_pair(u.first, n), y = make_pair(v.first, n);
for (auto p : all[i]) {
if (p != n - 1 && b[p] + 1 == b[p + 1]) {
pair<int, int> value(1 + (u.second + 1 != p ? u.first : v.first), all[i + 1].size() == 1 ? n : p);
y = max(y, value);
if (x < y) {
swap(x, y);
}
}
}
u = x;
v = y;
}
printf("%d
", n - 1 - u.first);
return 0;
}
Boss Battle
특판 n≤3 n≤3의 경우, 그렇지 않으면 매번 boss의 가능한 위치를 1 1로 줄일 수 있으며, 답은 n-3 n-3이다.
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
printf("%d
", max(n - 2, 1));
return 0;
}
Connect the Dots
욕심은 현재의 합법적인 각도를 지키면 된다.
#include
using namespace std;
struct angle_t {
int x, y, turn;
angle_t(int x = 0, int y = 0, int turn = 0):x(x), y(y), turn(turn) {
}
angle_t operator - (const angle_t &b) const {
return angle_t(x - b.x, y - b.y, turn);
}
int where() const {
if (y < 0) {
if (x >= 0) {
return 3;
} else {
return 2;
}
} else if (y > 0) {
if (x <= 0) {
return 1;
} else {
return 0;
}
} else {
if (x <= 0) {
return 2;
} else {
return 0;
}
}
}
angle_t rotate() {
return angle_t(-x, -y, turn + (where() >= 2));
}
bool operator < (const angle_t &b) const {
if (turn != b.turn) {
return turn < b.turn;
} else if (where() != b.where()) {
return where() < b.where();
} else {
return x * b.y > y * b.x;
}
}
bool operator <= (const angle_t &b) const {
return !(b < *this);
}
bool operator > (const angle_t &b) const {
return b < *this;
}
bool operator >= (const angle_t &b) const {
return !(*this < b);
}
};
struct range_t {
angle_t l, r;
bool tl, tr;
range_t() {
}
range_t(angle_t angle) {
l = r = angle;
tl = tr = true;
}
bool in(angle_t angle) {
while (!(tl ? l <= angle : l < angle)) {
++angle.turn;
}
return tr ? angle <= r : angle < r;
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n = 4, answer = 1;
vector a(n * n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
int x;
scanf("%d", &x);
a[x - 1] = angle_t(i, j, 0);
}
}
range_t current(a[1] - a[0]);
for (int i = 2; i < n * n; ++i) {
angle_t delta = a[i] - a[i - 1];
if (current.in(delta)) {
current = range_t(delta);
} else {
++answer;
angle_t l = current.l.rotate(), r = current.r.rotate();
while (r > delta.rotate()) {
--r.turn;
}
while (r.rotate() <= delta) {
++r.turn;
}
while (l >= delta.rotate()) {
--l.turn;
}
while (l.rotate() < delta) {
++l.turn;
}
current = range_t(delta);
if (r > delta) {
current.r = r;
current.tr = false;
}
if (l < delta) {
current.l = l;
current.tl = false;
}
int diff = -current.l.turn;
current.l.turn += diff;
current.r.turn += diff;
}
}
printf("%d
", answer);
return 0;
}
Dunglish
모방하다.
#include
using namespace std;
typedef long long ll;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
vector<string> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
int m;
cin >> m;
map<string, int> correct, incorrect;
map<string, string> translation;
while (m--) {
string from, to, state;
cin >> from >> to >> state;
if (state == "correct") {
++correct[from];
} else {
++incorrect[from];
}
translation[from] = to;
}
ll ways = 1, ok = 1;
for (int i = 0; i < n; ++i) {
ways *= (correct[a[i]] + incorrect[a[i]]);
ok *= correct[a[i]];
}
if (ways == 1) {
for (int i = 0; i < n; ++i) {
cout << translation[a[i]] << (i == n - 1 ? '
' : ' ');
}
cout << (ok ? "correct" : "incorrect") << endl;
} else {
cout << ok << " correct" << endl;
cout << ways - ok << " incorrect" << endl;
}
return 0;
}
English Restaurant
탁자를 용량에 따라 정렬하고 마지막에 tt의 용량이 ∞∞인 탁자를 추가합니다.마지막 사람은 몇 개의 구간을 꽉 채웠을 것이다. 먼저 f[l][r]f[l][r][r]는 구간[l,r][l,r]만 앉은 테이블의 방안 수와 답안을 총화하고 마지막에 앉은 테이블의mid m i d를 매거한다. 양쪽은 하위 문제이고 마지막에 온 사람이 구간(al-1,amid](al-3-1,am i d)에 매거하면 옮길 수 있다.
뒤에서 앞으로 DP를 외우고 g[i][j]g[i][j]는 ii를 고려한 후의 시간을 나타낸다. 현재 구간의 가장 왼쪽 단점은 jj의 방안수와 답안을 합친 것이다. 옮길 때 지난번에 옮긴 시간과 지난번 구간의 시작 위치를 일일이 열거하고 접두사와 최적화를 사용하면 된다.
#include
using namespace std;
typedef long double ld;
pair operator + (pair a, pair b) {
return make_pair(a.first + b.first, a.second + b.second);
}
pair operator * (pair a, pair b) {
return make_pair(a.first * b.second + a.second * b.first, a.second * b.second);
}
int sum(int x) {
return x * (x + 1) >> 1;
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n, group, hours;
scanf("%d %d %d", &n, &group, &hours);
vector<int> a(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
a[i] = min(a[i], group);
}
sort(a.begin(), a.end());
for (int i = 0; i < hours; ++i) {
a.push_back(group + 1);
++n;
}
vector<vector > binom(n + 1);
for (int i = 0; i <= n; ++i) {
binom[i].push_back(1);
for (int j = 1; j <= i; ++j) {
binom[i].push_back((j != i ? binom[i - 1][j] : 0) + binom[i - 1][j - 1]);
}
}
vector<vector >> dp(n, vector > (n));
for (int j = 0; j < n; ++j) {
for (int i = j; ~i; --i) {
for (int k = i; k <= j; ++k) {
pair value = make_pair(0, binom[j - i][k - i]);
value = value * make_pair(a[k] == group + 1 ? 0 : sum(a[k]) - sum(i ? a[i - 1] : 0), min(a[k], group) - (i ? min(a[i - 1], group) : 0));
if (k != i) {
value = value * dp[i][k - 1];
}
if (k != j) {
value = value * dp[k + 1][j];
}
dp[i][j] = dp[i][j] + value;
}
}
}
vector<vector >> f(hours, vector > (n)), sum(hours, vector > (n));
for (int i = 0; i < hours; ++i) {
for (int j = 0; j <= n + i - hours; ++j) {
f[i][j] = dp[j][j + hours - i - 1];
}
}
for (int i = hours - 1; ~i; --i) {
for (int j = n - 1; ~j; --j) {
for (int k = i + 1; k < hours; ++k) {
if (j + k - i + 1 < n) {
pair value = make_pair(0, binom[hours - i][hours - k]);
value = value * dp[j][j + k - i - 1] * sum[k][j + k - i + 1];
f[i][j] = f[i][j] + value;
}
}
sum[i][j] = f[i][j];
if (j + 1 < n) {
sum[i][j] = sum[i][j] + sum[i][j + 1];
}
}
}
pair answer;
for (int i = 0; i < n; ++i) {
answer = answer + f[0][i];
}
printf("%.8lf
", (double)(answer.first / answer.second));
return 0;
}
Factor-Free Tree
분해질 인수는 왼쪽에서 오른쪽으로 가장 먼 곳까지 모든 것과 호환성을 구하고 중간 순서에 따라 전체 서열을 두루 고려한다. 한 창고는 이전의 가장 오른쪽 체인을 표시하고 새로운 점이 생길 때마다 먼저 아래로 걸어서 아버지의 rr가 자신의 rr보다 크거나 그의 ll가 왼쪽의 자수를 덮을 수 없을 때까지 위로 올라가려고 한다.
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
vector<int> a(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
int m = *max_element(a.begin(), a.end());
vector<int> min_prime(m + 1), primes;
for (int i = 2; i <= m; ++i) {
if (!min_prime[i]) {
min_prime[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > m) {
break;
}
min_prime[i * p] = p;
if (i % p == 0) {
break;
}
}
}
vector<int> l(n), r(n), last(m + 1, -1);
for (int i = 0; i < n; ++i) {
l[i] = -1;
int x = a[i];
while (x != 1) {
int p = min_prime[x];
l[i] = max(l[i], last[p]);
last[p] = i;
while (x % p == 0) {
x /= p;
}
}
++l[i];
}
for (int i = 0; i <= m; ++i) {
last[i] = n;
}
for (int i = n - 1; ~i; --i) {
r[i] = n;
int x = a[i];
while (x != 1) {
int p = min_prime[x];
r[i] = min(r[i], last[p]);
last[p] = i;
while (x % p == 0) {
x /= p;
}
}
--r[i];
}
vector<int> answer(n);
vectorint , int>, int>> stack(n + 1);
stack[0].first.second = -1;
int top = 0;
for (int i = 0; i < n; ++i) {
stack[top + 1].first.second = -1;
int temp = i;
while (top && l[i] <= stack[top].first.first && r[i] >= stack[top].second) {
temp = min(temp, stack[top].first.first);
--top;
}
if (~stack[top + 1].first.second) {
answer[stack[top + 1].first.second] = i;
}
answer[i] = stack[top].first.second;
int right = top ? stack[top].second : n;
if (right < i) {
puts("impossible");
return 0;
}
stack[++top] = make_pair(make_pair(temp, i), min(r[i], right));
}
for (int i = 0; i < n; ++i) {
printf("%d%c", answer[i] + 1, i == n - 1 ? '
' : ' ');
}
return 0;
}
Glyph Recognition
매거 변수는 공식적으로 두 개의 bound를 계산해 낼 수 있고 직접 계산하면 된다.
#include
using namespace std;
typedef long long ll;
typedef long double ld;
const ld pi = acosl(-1);
const ld inf = 1e9;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
vector<int> x(n), y(n);
for (int i = 0; i < n; ++i) {
scanf("%d %d", &x[i], &y[i]);
}
ld answer = 0;
int best = -1;
for (int i = 3; i <= 8; ++i) {
ld inner = inf, outer = 0;
for (int j = 0; j < n; ++j) {
ld angle = atan2(y[j], x[j]);
while (angle < 0) {
angle += 2 * pi / i;
}
while (angle >= 2 * pi / i) {
angle -= 2 * pi / i;
}
ld dist = sqrtl((ll)x[j] * x[j] + (ll)y[j] * y[j]) * cosl(angle - pi / i);
inner = min(inner, dist);
outer = max(outer, dist);
}
ld ratio = inner / outer;
ratio *= ratio;
if (ratio > answer) {
answer = ratio;
best = i;
}
}
printf("%d %.8lf
", best, (double)answer);
return 0;
}
High Score
제곱의 성장이 비교적 빠르기 때문에 작은 두 개가 얼마나 증가했는지 매거할 수 있다. 이 값은 크지 않고 폭력이면 된다.
#include
using namespace std;
typedef long long ll;
ll calc(int a, int b, int c) {
return (ll)a * a + (ll)b * b + (ll)c * c + 7ll * min(a, min(b, c));
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
int a, b, c, d;
scanf("%d %d %d %d", &a, &b, &c, &d);
ll answer = 0;
for (int i = 0; i <= d && i <= 100; ++i) {
for (int j = 0; i + j <= d && j <= 100; ++j) {
int k = d - i - j;
answer = max(answer, calc(a + i, b + j, c + k));
answer = max(answer, calc(a + i, b + k, c + j));
answer = max(answer, calc(a + k, b + i, c + j));
}
}
printf("%lld
", answer);
}
return 0;
}
Installing Apps
만약에 모든 것을 선택한다면 가장 좋은 순서는 반드시 max(d,s) - d max(d,s) - - d에 따라 큰 것부터 작은 것까지 순서를 정하고 f(i,j) f(i,j)를 외우는 것이 전 ii의 물품을 고려하고 j개를 선택했는데 최소한 얼마의 공간을 차지했는지 나타낸다.
#include
using namespace std;
struct info_t {
int need, get, id;
info_t(int need = 0, int get = 0, int id = 0):need(need), get(get), id(id) {
}
bool operator < (const info_t &b) const {
return get > b.get;
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n, size;
scanf("%d %d", &n, &size);
vector apps(n);
for (int i = 0; i < n; ++i) {
int disk, storage;
scanf("%d %d", &disk, &storage);
apps[i] = info_t(max(disk, storage), max(disk, storage) - storage, i);
}
sort(apps.begin(), apps.end());
vector<vector<int>> f(n + 1, vector<int> (n + 1, size + 1));
vector<vector<bool>> g(n + 1, vector<bool> (n + 1, false));
f[0][0] = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= i; ++j) {
f[i + 1][j] = f[i][j];
}
for (int j = 0; j <= i; ++j) {
if (f[i][j] + apps[i].need <= size && f[i + 1][j + 1] > f[i][j] + apps[i].need - apps[i].get) {
f[i + 1][j + 1] = f[i][j] + apps[i].need - apps[i].get;
g[i + 1][j + 1] = true;
}
}
}
for (int i = n; ~i; --i) {
if (f[n][i] <= size) {
printf("%d
", i);
if (i) {
vector<int> answer;
for (int j = n, current = i; j; --j) {
if (g[j][current]) {
--current;
answer.push_back(apps[j - 1].id);
}
}
reverse(answer.begin(), answer.end());
for (int j = 0; j < answer.size(); ++j) {
printf("%d%c", answer[j] + 1, j == answer.size() - 1 ? '
' : ' ');
}
}
return 0;
}
}
return 0;
}
Juggling Troupe
22마다 단독으로 고려하여 ii라고 가정하고 그 좌우의 000의 위치 l,rl,r를 구하면 l,rl,r를 1로 부여하고 l+r-3-i l+r-3을 0으로 부여한다.set로 유지보수하면 됩니다.
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
string str;
cin >> str;
int n = str.length();
set<int> s;
s.insert(-1);
s.insert(n);
for (int i = 0; i < n; ++i) {
if (str[i] == '0') {
s.insert(i);
}
}
for (int i = 0; i < n; ++i) {
if (str[i] == '2') {
auto l = s.lower_bound(i), r = l;
--l;
int x = *l + *r - i;
if (~*l) {
s.erase(l);
}
if (*r < n) {
s.erase(r);
}
s.insert(x);
}
}
string answer(n, '1');
for (auto p : s) {
if (p >= 0 && p < n) {
answer[p] = '0';
}
}
cout << answer << endl;
return 0;
}
Knockout Tournament
a1a1을 0 0으로 보고 aa에 따라 작은 순서에서 큰 순서로 인접한 매칭이 가장 좋다.그리고 트리 DP를 만들면 됩니다.
#include
using namespace std;
typedef long double ld;
void dfs(int x, int m, int &index, vector<vectorint , ld>>> &f) {
if ((x << 1 | 1) >= m) {
f[x].push_back(make_pair(--index, 1));
} else {
dfs(x << 1 | 1, m, index, f);
dfs(x + 1 << 1, m, index, f);
}
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
vector<int> a(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
int first = a[0];
a[0] = 0;
sort(a.begin(), a.end());
a[0] = first;
int m = (n << 1) - 1, binary = 1;
while ((binary << 1 | 1) <= m) {
binary = binary << 1 | 1;
}
vector<vectorint , ld>>> f(m);
int index = n;
dfs(0, m, index, f);
for (int i = m - n - 1, j = 0; ~i; --i) {
int l = i << 1 | 1, r = i + 1 << 1;
for (int rotate = 0; rotate < 2; ++rotate) {
for (auto p : f[l]) {
int index = p.first;
ld prob = 0;
for (auto q : f[r]) {
prob += q.second * a[index] / (a[index] + a[q.first]);
}
f[i].push_back(make_pair(index, prob * p.second));
}
swap(l, r);
}
}
for (auto p : f[0]) {
if (!p.first) {
printf("%.8lf
", (double)p.second);
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.