Codeforces Round #693 (Div. 3)

Contest Info


Practice Link

SolvedABCDEFG
5/7OOOOØ--
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


A. Cards for Friends

题意:
给你一个 w w w x h h h的明信片,当 h h h w w w为偶数时可以剪成两份,问你最终能剪出来的数量是否比 n n n大。

思路:
刚开始总数为 1 1 1,每剪一次乘上 2 2 2

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define dbg(x...)             \
    do {                      \
        cout << #x << " -> "; \
        err(x);               \
    } while (0)

void err() {
    cout << endl;
}

template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
    cout << arg << ' '; err(args...);
}
template <class T> inline void read(T &x) {
    int f = 0; x = 0; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if (f) x = -x;
}

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;

ll tot = 1;

void work(ll n) {
    while (n % 2 == 0) {
        n /= 2;
        tot <<= 1;
    }
}

ll w, h, n;
void solve() {
    cin >> w >> h >> n;
    tot = 1;
    work(w);
    work(h);
    cout << (tot >= n? "YES" : "NO") << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout << fixed << setprecision(20);
    int _T = 1;
    cin >> _T;
    while (_T--) solve();
}

B. Fair Division

题意:
给出 n n n颗糖果,每颗糖果的重量为 1 1 1或者 2 2 2,问这些糖果是否可以均分成重量相同的两份。

思路:
1 1 1的数量不为偶数肯定不行,接下来考虑 2 2 2的数量。当 2 2 2的数量为奇数时考虑能否用两个 1 1 1来使之平衡。

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define dbg(x...)             \
	do {                      \
		cout << #x << " -> "; \
		err(x);               \
	} while (0)

void err() {
	cout << endl;
}

template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
	cout << arg << ' '; err(args...);
}
template <class T> inline void read(T &x) {
	int f = 0; x = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
	if (f) x = -x;
}

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;

int num1, num2, n;

void solve() {
	cin >> n;
	num1 = num2 = 0;
	for (int i = 1, t; i <= n; ++i) {
		cin >> t;
		if (t == 1) num1++;
		else num2++;
	}
	if (num1 & 1) {
		cout << "NO" << endl;
		return;
	}
	if (num2 % 2 == 0) {
		cout << "YES" << endl;
		return;
	}
	if (num1 >= 2) {
		cout << "YES";
	}
	else cout << "NO";
	cout << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);cout.tie(nullptr);
	cout << fixed << setprecision(20);
	int _T = 1;
	cin >> _T;
	while (_T--) solve();
}

C. Long Jumps

题意:
给你一段元素权值为正整数的序列,你可以从任意一点出发,每次跳到当前点的后第当前权值个点,直到跳出序列。问你一路上经过的点权值和最大是多少。

思路:
很明显要记忆化。

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define dbg(x...)             \
    do {                      \
        cout << #x << " -> "; \
        err(x);               \
    } while (0)

void err() {
    cout << endl;
}

template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
    cout << arg << ' '; err(args...);
}
template <class T> inline void read(T &x) {
    int f = 0; x = 0; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if (f) x = -x;
}

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 7;

ll dp[N], a[N];
ll n;

ll dfs(ll u) {
    if (u > n) return 0;
    if (dp[u]) return dp[u];
    dp[u] += a[u] + dfs(u + a[u]);
    return dp[u];
}

void solve() {
    cin >> n;
    ll maxx = -INF;
    for (ll i = 1; i <= n; ++i) {
        cin >> a[i];
        dp[i] = 0;
    }
    for (ll i = 1; i <= n; ++i) {
        maxx = max(maxx, dfs(i));
    }
    cout << maxx << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout << fixed << setprecision(20);
    int _T = 1;
    cin >> _T;
    while (_T--) solve();
}

D. Even-Odd Game

题意
给你一段元素权值为正整数的序列,两个人可以不放回地取出里面的元素。先手取权值为偶数的数时,将自己的分数加上当前数,否则直接丢弃。后手则加奇数,直接弃偶数。问最优情况下的获胜情况。

思路:
想一下发现我们每次可以贪心的去取最大值,要么让对方取不到最大值,要么就能让自己取到最大值。

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define dbg(x...)             \
    do {                      \
        cout << #x << " -> "; \
        err(x);               \
    } while (0)

void err() {
    cout << endl;
}

template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
    cout << arg << ' '; err(args...);
}
template <class T> inline void read(T &x) {
    int f = 0; x = 0; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if (f) x = -x;
}

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 7;

ll a[N];
int n;

void solve() {
    cin >> n;
    ll ansOdd = 0, ansEven = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    sort(a + 1, a + 1 + n, greater<ll>());
    for (int i = 1; i <= n; ++i) {
        if ((i - 1) & 1) {
            if (a[i] & 1) ansOdd += a[i];
        } else if (a[i] % 2 == 0) ansEven += a[i];
    }
    if (ansOdd > ansEven) cout << "Bob" << endl;
    else if (ansOdd < ansEven) cout << "Alice" << endl;
    else cout << "Tie" << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout << fixed << setprecision(20);
    int _T = 1;
    cin >> _T;
    while (_T--) solve();
}

E. Correct Placement

题意:
n n n个人,第 i i i个人的高和宽为 h i h_i hi w i w_i wi。选 i i i j j j两个人,若满足条件 h j h_j hj < h i h_i hi and w j w_j wj < w i w_i wi 或者 w j w_j wj < h i h_i hi and h j h_j hj < w i w_i wi,则称第 j j j个人可以排在第 i i i个人前面。现在问每个人是否有人可以在他前面。

思路:
我们考虑将 h i h_i hi设为 h i h_i hi w i w_i wi中的较小值, w i w_i wi h i h_i hi w i w_i wi中的较大值,那么就只用判断 h j h_j hj < h i h_i hi and w j w_j wj < w i w_i wi的条件了(贪心地让小的和小的比,大的和大的比)。那么接下来我们以 h h h为第一关键字, w w w为第二关键字,由小到大 s o r t sort sort一下。然后以 1 1 1为最小的元素,遍历数组,判断条件。期间记录下遍历过的值中 w w w最小的位置在哪里,当 h h h的值变化两次后(因为要严格小于),则改变最小的元素所在的位置。注意当 h h h值变化达到两次后,下次只用再变化一次就行了。因为变化对上一次和下一次都是有贡献的。

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define dbg(x...)             \
    do {                      \
        cout << #x << " -> "; \
        err(x);               \
    } while (0)

void err() {
    cout << endl;
}

template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
    cout << arg << ' '; err(args...);
}
template <class T> inline void read(T &x) {
    int f = 0; x = 0; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if (f) x = -x;
}

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 7;

struct Friend{
    int h, w, id;

    Friend(int h, int w, int id) : h(h), w(w), id(id) {}
    Friend () {}
}f[N];

bool cmp(Friend a, Friend b) {
    if (a.h == b.h) return a.w < b.w;
    return a.h < b.h;
}

int n, ans[N];

void solve() {
    read(n);
    for (int i = 1, h, w; i <= n; ++i) {
        read(h), read(w);
        f[i] = Friend(min(h, w), max(h, w), i);
        ans[i] = -1;
    }
    sort(f + 1, f + 1 + n, cmp);
    int now = 1, nxt = 1, minn = f[1].w, sta = 0;
    for (int i = 2; i <= n; ++i) {
        if (f[i].h != f[i - 1].h) sta++;
        if (sta > 1) {
            sta = 1;
            now = nxt;
        }
        if (f[i].h > f[now].h && f[i].w > f[now].w) {
            ans[ f[i].id ] = f[now].id;
        }
        if (minn > f[i].w) {
            minn = f[i].w;
            nxt = i;
        }
    }
    for (int i = 1; i <= n; ++i) {
        printf("%d%c", ans[i], " \n"[i == n]);
    }
}

int main() {
    // ios::sync_with_stdio(false);
    // cin.tie(nullptr);cout.tie(nullptr);
    // cout << fixed << setprecision(20);
    int _T = 1;
    read(_T);
    while (_T--) solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值