目次
A:
https://codeforces.com/contest/1472/problem/A
アイデア:一枚の紙の水平方向と垂直方向のカットの数は固定されており、それを掛けるだけです。
#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
ll w,h,n;
scanf("%lld%lld%lld",&w,&h,&n);
int ww=0,hh=0;
while(w % 2 == 0){ww++;w/=2;}
while(h % 2 == 0){hh++;h/=2;}
ww = pow(2,ww);
hh = pow(2,hh);
ll maxn = ww*hh;
if(maxn>=n)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
B:
https://codeforces.com/contest/1472/problem/B
アイデア:すべての糖の重量の合計が奇数である場合、何があっても、それらを分割することは不可能です。合計が偶数の場合、2で割った結果が奇数か偶数かを判断する必要があります。
結果が偶数の場合は、除算できます。結果が奇数の場合、2つおきの1は2に相当し、奇数の構成は偶数の束になります。指定された数の1の数が2以上である限り、1を加算するだけです。奇数除算法の構造を実現できます。
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
int s1=0,s2=0,sum=0;
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
if(t == 1) s1++;
if(t == 2) s2++;
}
sum = s1+2*s2;
if(sum % 2 == 1)
{
cout<<"NO"<<endl;
continue;
}
int each = sum/2;
if(each % 2 == 1)
{
if(s1>=2)
{
cout<<"YES"<<endl;
continue;
}
else
{
cout<<"NO"<<endl;
continue;
}
}
if(each % 2 == 0)
{
cout<<"YES"<<endl;
continue;
}
}
return 0;
}
C:
https://codeforces.com/contest/1472/problem/C
アイデア:質問の意味を理解した後、プロセス全体をシミュレートし、最大値を記録します。ただし、最適化には注意してください。トラバースの逆順(メモ化の方法と同様に、このポイントから最後のジャンプまでの回答はta配列の対応するインデックスに格納され、前のポイントはそれにジャンプして値を直接読み取り、時間の複雑さを最適化できます)
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
ll a[200005],ta[200005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
ll mmax = -1;
for(int i=n;i>=1;i--)
{
ll tans=0;
int crs=i;
tans+=a[crs];
if(crs+a[crs]<=n)
tans += ta[crs+a[crs]];
ta[crs] = tans;
mmax = max(mmax,tans);
}
cout<<mmax<<endl;
}
return 0;
}
D:
https://codeforces.com/contest/1472/problem/D
アイデア:ゲーム理論、貪欲な思考、すべてのステップが自分にとって最良の選択であることを確認します。最初に並べ替えます。明らかに最大のものから始めます。ラウンドの場合は、自分にポイントを追加する番号を選択するか、現時点で対戦相手の最大の番号を選択するかを選択できます(対戦相手がこの番号を選択すると、現在選択している自分の番号よりも不利になります:この時点での最大数が自分の最大数よりも大きい場合は、この時点での対戦相手の最大数を選択します)。ps。他の人にポイントを追加させるよりも、他の人にポイントを追加したくない。。貪欲すぎるorz
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 200005
using namespace std;
ll ev[N],od[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
int evn=0,odn=0;
for(int i=1;i<=n;i++)
{
ll t;
scanf("%lld",&t);
if(t % 2 == 0)
{
evn++;
ev[evn]=t;
}
else
{
odn++;
od[odn]=t;
}
}
sort(ev+1,ev+evn+1);
sort(od+1,od+odn+1);
ll aans=0,bans=0;
int evc=evn,odc=odn;
for(int i=1;i<=n;i++)
{
if(i%2 == 1) // alice
{
if(evc>=1 && ev[evc]>=od[odc])
{
aans+=ev[evc];
evc--;
}
else
{
odc--;
}
}
else // bob
{
if(odc>=1 && od[odc]>=ev[evc])
{
bans+=od[odc];
odc--;
}
else
{
evc--;
}
}
}
if(aans == bans)
{
cout<<"Tie"<<endl;
}
if(aans > bans)
{
cout<<"Alice"<<endl;
}
if(aans < bans)
{
cout<<"Bob"<<endl;
}
}
return 0;
}
E:
https://codeforces.com/contest/1472/problem/E
アイデア:横になって座っているかどうかにかかわらず、最初の次元(x)は小と中の両方の数であり、2番目の次元(y)は両方とも数が多く、x、yの降順処理に昇順であるため、非常に統一されています。巧妙に、この方法は、tidでマークされたポイントのy値が現在の状態で最小になるようにするために使用されます(xが順序付けられているため、xはより小さい必要があります)。したがって、タイトルの要件を満たしているかどうかを判断します。回答を記録し、tid値が満たされない場合は(b値を小さくするために)更新することで、時間の複雑さを軽減します。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct peo{
long long x,y;
long long id;
}p[300005];
long long ans[300005];
bool cmp(peo a,peo b)
{
if(a.x == b.x)
return a.y>b.y;
return a.x<b.x;
}
int main()
{
long long T;
cin>>T;
while(T--)
{
long long n;
scanf("%lld",&n);
long long ta,tb;
for(long long i=1;i<=n;i++)
{
scanf("%lld%lld",&ta,&tb);
p[i].id=i;
p[i].x=min(ta,tb);
p[i].y=max(ta,tb);
}
sort(p+1,p+n+1,cmp);
int tid=1;
for(long long i=1;i<=n;i++)
{
long long t=-1;
if(p[i].y > p[tid].y)
{t=p[tid].id;}
if(p[i].y < p[tid].y)
{tid=i;}
ans[p[i].id] = t;
//printf("%s\n", );
}
for(long long i=1;i<=n;i++)
{
printf("%lld",ans[i]);
if(i!=n) printf(" ");
}
cout<<endl;
}
return 0;
}