Codeforces Round #693 (Div. 3)

目录

  • Contest Info
  • Solution
    • A. Cards for Friends
    • B. Fair Division
    • C. Long Jumps
    • D. Even-Odd Game
    • E. Correct Placement

Contest Info


Practice Link

Solved A B C D E F G
5/7 O O O O Ø - -
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solution


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 

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 

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 

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 

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 

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();
}

你可能感兴趣的:(codeforces)