Codeforces Global Round 14
A.Phoenix and Gold
- 题意
问你能不能重排 n n n 个物品,然后使得 ∑ j = 1 i w j ≠ x \sum\limits_{j=1}^{i}w_j\neq x j=1∑iwj=x 其中 ( 1 ≤ i ≤ n ) (1 \leq i \leq n) (1≤i≤n)
- 思路
比较简单,直接看代码吧。注意排序 - 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
#define ll long long
void solve()
{
int n,x;
cin>>n>>x;
int sum=0;
for(int i=1;i<=n;i++){
cin>>a[i];sum+=a[i];
}
if(sum==x) {cout<<"NO"<<endl;return;}
sum=0;
cout<<"YES"<<endl;
sort(a+1,a+1+n);
int tt,flag=0;
for(int i=1;i<=n;i++){
sum+=a[i];
if(sum!=x){
cout<<a[i]<<" ";
}
else{
tt=a[i];flag=1;
sum-=a[i];
continue;
}
}
if(flag){
cout<<tt<<endl;
}
else{
cout<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
}
B.Phoenix and Puzzle
- 题意
问你能不能用 n n n 个同样大小的等腰直角三角形拼成一个正方形。
- 思路
一开始以为是2的幂次就行,然后过不了。所以就考虑面积。因为边长肯定是 2 \sqrt2 2 的倍数或者是整数,所以看代码 - 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
#define ll long long
set<ll> ans;
void solve()
{
ll n;
cin>>n;
if(n%2==1){cout<<"NO"<<endl; return ;}
if(ans.find(n/2)!=ans.end()||(n%4==0&&ans.find(n/4)!=ans.end())){
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
int main()
{
ll x=2;
for(ll i=1;i*i<=1ll*1e10;i++){
ans.insert(i*i);
}
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
}
C. Phoenix and Towers
- 题意
给你 n n n 个 h e i g h t height height ,然后垒成 m m m 个塔,问你能不能使得这 m m m 个塔任意的高度差不超过 x x x .
- 思路
不会做,太菜了,看的官方题解。就是用一个大根堆,就是优先队列的思想,每次加到最小的那一个。看代码
正确性:反证法。如果最后不成功,那么一定有两个塔高度差会超过 x ~x~ x .但是每一个 h e i g h t ~height~ height 不会超过 x x x .
画个图解释一下。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
#define PII pair<int,int>
#define x first
#define y second
int a[maxn];
const int eps=1e-6;
#define ll long long
void solve()
{
set<pair<int,int> > ans;
int n,m,x;
cin>>n>>m>>x;
for(int i=1;i<=m;i++){
ans.insert({0,i});
}//先提前生成m个塔
cout<<"YES"<<endl;
for(int i=1;i<=n;i++){
cin>>a[i];
//每次把a[i] 放到最小的那一个塔。
pair<int,int> p=*ans.begin();
ans.erase(ans.begin());
ans.insert({p.x+a[i],p.second});
cout<<p.y<<" ";
}
cout<<endl;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
}
D. Phoenix and Socks
-
题意
-
思路
枚举颜色,先把可以配对的去掉,然后配每一个颜色。
-
代码
#include <bits/stdc++.h>
using namespace std;
int N,L,R;
int C[200001];
int lcnt[200001],rcnt[200001];
void solve(){
cin>>N>>L>>R;
for (int i=1;i<=N;i++){
lcnt[i]=0;
rcnt[i]=0;
}
for (int i=1;i<=N;i++){
cin>>C[i];
if (i<=L)
lcnt[C[i]]++;
else
rcnt[C[i]]++;
}
//remove pairs that are already matching
for (int i=1;i<=N;i++){
int mn=min(lcnt[i],rcnt[i]);
lcnt[i]-=mn;
rcnt[i]-=mn;
L-=mn;
R-=mn;
}
if (L<R){
swap(lcnt,rcnt);
swap(L,R);
}
//now, there are at least as many left socks as right socks
int ans=0;
for (int i=1;i<=N;i++){
int extra=L-R; //always even
int canDo=lcnt[i]/2;
int Do=min(canDo*2,extra);
//turn "Do"/2 left socks of color i into right socks
ans+=Do/2;
L-=Do;
}
//turn extra lefts into rights, then adjust all colors
ans+=(L-R)/2+(L+R)/2;
cout<<ans<<endl;
}
int main()
{
ios_base::sync_with_stdio(0);cin.tie(0);
int T; cin>>T;
while (T--)
solve();
return 0;
}