件名リンク: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;
}