Codeforces Round#693(Div。3)問題解決レポート

件名リンク:https//codeforces.com/contest/1472

A.友達のためのカード

トピック

一枚の紙の長さはw、幅はhです。wまたはhが偶数の場合は、半分の紙に分割できます。2枚の紙について同じ操作を繰り返し、1枚の紙かどうかを確認します。 n以上に分けることができます

アイデア

wとhを別々に分解し、分割できなくなるまで2で除算し、t1とt2の部分に分割して、合計でt1 * t2の部分になります。

ここでは、強制的に除算することも、ビット演算を直接使用することもできます。つまり、ロービットです(バイナリの最後の1の位置から残っている数値を取得します)。

ACコード

暴力

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
	int t; cin >> t;
	while(t --){
		int w, h, n;
		cin >> w >> h >> n;
		int t1 = 1, t2 = 1;
		while(w % 2 == 0) {
			t1 *= 2;
			w /= 2;
		}
		while(h % 2 == 0){
			t2 *= 2;
			h /= 2;
		}
		if(t1 * t2 >= n) puts("YES");
		else puts("NO");
	}
	return 0;
}

ロービット

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x & (-x)
int main(){
	int t; cin >> t;
	while(t --){
		int w, h, n;
		cin >> w >> h >> n;
		int t1 = lowbit(w), t2 = lowbit(h);
		if(t1 * t2 >= n) puts("YES");
		else puts("NO");
	}
	return 0;
}

B.公平分割

トピック

n個の砂糖、重さは1または2のいずれかで、同じ重さの2つの部分に分割できるかどうかを尋ねます

アイデア

1の数、t1、2の数、t2、および総重量sを見つけます。

sが奇数の場合、それは間違いなく機能しません。

半分に分けた場合、一人一人に割り当てられる重みは奇数ですが、重みが1のキャンディーはありません。

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
	int t; cin >> t;
	while(t --){
		int s = 0, n, t1 = 0, t2 = 0, x;
		cin >> n;
		while(n --){
			cin >> x;
			t1 += (x == 1);
			t2 += (x == 2);
			s += x;
		}
		if(s % 2){
			puts("NO");
			continue;
		}
		s /= 2;
		if(s % 2 && !t1) puts("No");
		else puts("YES"); 
	}
	return 0;
}

C.ロングジャンプ

トピック

n個の数値はi番目の位置から配列aに格納され、中央の位置ttはiに初期化され、a [tt]の距離は毎回ジャンプできます。

tt <= nの場合、ジャンプを続行できます。それ以外の場合、ゲームは終了します。tmpは、途中のジャンプの重みの合計であり、このtmpの最大値を尋ねます。

アイデア

各位置は常にジャンプしてnからジャンプできます。たとえば、左から右にトラバースすると、1が6にジャンプし、3が6にジャンプできる場合、ここで6は2回ジャンプし、多くの繰り返し操作、しかし、後ろから前にトラバースできるので、メモ化と同等であり、1回のジャンプで十分です。

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
ll a[maxn], dp[maxn]; // dp[i]就是从i位置开始跳出n需要加的权值
int main(){
	int t; cin >> t;
	while(t --){
		int n; scanf("%d",&n);
		for(int i = 1; i <= n; i ++){
			scanf("%lld", &a[i]);
		}
		for(int i = 1; i <= n; i ++) dp[i] = 0;
		ll ans = 0;
		for(int i = n; i >= 1; i --){
			ll d = i + a[i];
			dp[i] += a[i] + (d <= n ? dp[d] : 0);
			ans = max(ans, dp[i]);
		}
		cout << ans << endl;
	}
	return 0;
}

D.偶数-奇数ゲーム

トピック

二人が交代でn個の石を取り終えるまで取ります。アリスが最初に、ボブが2番目になります。

アリスが取った石の重量wiが偶数の場合、彼女のスコアはwiに追加されます。それ以外の場合、スコアは追加されません。

ボブが取った石の重量wiが奇数の場合、彼のスコアはwiに追加されます。それ以外の場合、スコアは追加されません。

最終的に誰が勝つか引き分けかを尋ねます。

アイデア

選択したい場合は、毎回最も重いものを選択する必要があります。ポイントを追加する最良の方法。ポイントを追加できない場合は、ポイントを追加している必要があります。いいえ、追加できません。彼を連れて行ってください。 。

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
ll a[maxn];
int main(){
	int t; cin >> t;
	while(t --){
		int n, x; cin >> n;
		ll t1 = 0, t2 = 0;
		for(int i = 1; i <= n; i ++) {
			cin >> a[i];
		}
		sort(a + 1, a + n + 1, greater<int>()); //从大到小排序
		for(int i = 1; i <= n; i ++){
			if(i % 2 == 1 && a[i] % 2 == 0) t1 += a[i]; //Alice先手 偶数加分
			if(i % 2 == 0 && a[i] % 2 == 1) t2 += a[i]; //Bob后手 奇数加分
		}
		if(t1 > t2) puts("Alice");
		else if(t1 < t2) puts("Bob");
		else puts("Tie");
	}
	return 0;
}

E.正しい配置

トピック

写真を撮るためにN人の子供が並んでおり、各子供には長さと幅の属性wi、hiがあります。iをjの前にランク付けする場合は、wi <wj && hi <hjまたはwi <hj && hi <wjを満たす必要があります。

次に、各子iを要求し、子の前に配置できる添え字(任意)を出力します。存在しない場合は、-1を出力します。

アイデア

まず、wiが(wi、hi)の中で小さい値であり、hiが(wi、hi)の中で大きい値であると規定されている場合、条件wi <wj && hi <hjが満たされているかどうかを確認するだけで済みます。

次に、最初にwiで並べ替え、次にhiで並べ替えて、左側のwが右側のw以下になるようにします。

ダブルポインタのアイデア、i、j。iは配列をトラバースし、jは追跡します。a[j] .w <a [i] .wの場合、tmpはa [j] .hの最小値を更新し、idは、tmp <aの場合、更新された最小値の位置です。 [i] .hの場合、この時点でid位置にある子は子a [i] .idの前に立つことができます。

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x & (-x)
#define pp pair<int, int>
const int maxn = 2e5 + 10;
struct node{
	int x, y, id;
	bool operator < (const node &a) const{
		if(x != a.x) return x < a.x;
		return y < a.y;	
	}
}a[maxn];
int dp[maxn];
int main(){
	int t, n;
	cin >> t;
	while(t --){
		cin >> n;
		for(int i = 1; i <= n; i ++){
			cin >> a[i].x >> a[i].y;
			if(a[i].x > a[i].y) swap(a[i].x, a[i].y);
			a[i].id = i; dp[i] = -1;
		}
		sort(a + 1, a + n + 1);
		int tmp = 0x3f3f3f3f, id = -1, j = 1;
		for(int i = 1; i <= n; i ++){
			while(j < i && a[j].x < a[i].x){
				if(tmp > a[j].y){
					tmp = a[j].y;
					id = a[j].id;
				} j ++;
			}
			if(tmp < a[i].y) dp[a[i].id] = id;
		}
		for(int i = 1; i <= n; i ++){
			if(i > 1) cout << " ";
			cout << dp[i];
		}
		cout << endl;
	}
	return 0;
}

 

おすすめ

転載: blog.csdn.net/weixin_43911947/article/details/112217993