Dashboard - Codeforces Round #840 (Div. 2) and Enigma 2022 - Cybros LNMIIT - Codeforces
A. Absolute Maximization
题意:给定一个长度为n的数组a,可以执行该操作任意次:选第 i 个和第 j 个数交换两者二进制下第 b 位。 确定 max(a)- min(b) 的最大值。
思路:使最大值尽可能大最小值尽可能小,对于最大值二进制每一位,如果所有数该位上有1,则最大值这一位肯定能通过交换得到1,使最大值尽可能的得到1即能使尽可能地的大。最小值同理,使其尽可能的得到0即能使其尽可能的小。故答案为 所有数的或-与
#include<bits/stdc++.h>
// #define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0);cin.tie(0)
using namespace std;
const int N=1e5+10;
int n;
int a[N];
void solve(){
cin >> n;
for(int i=0;i<n;i++) cin >> a[i];
int num=a[0];
int num1=num;
for(int i=0;i<n;i++){
num|=a[i];
num1&=a[i];
}
cout << num-num1 << endl;
}
signed main(){
int t=1;
cin >> t;
while(t--){
solve();
}
}
B. Incinerate
题意:有 n 只怪物,每只怪物的血量和力量分别为 ai 和 bi,玩家攻击力初始为k,每次攻击可以攻击所有怪物使其血量减小k(怪物血量<=0为死亡),同时玩家的攻击力减少所有存活怪物里最小的力量,问玩家是否可以击杀所有怪物。
思路:(1)用优先队列维护怪物的力量即可(小根堆),记录打出的攻击和,若当前对头的怪物血量小于等于攻击和(死掉了)弹出,否则当前怪物的力量就是下次攻击要减少的值,若攻击和大于等于最大怪物血量则YES,若k<0 且此时攻击和还未大于等于最大怪物血量则NO,模拟此过程即可。
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0);cin.tie(0)
using namespace std;
const int N=1e5+10;
int n,k;
int a[N],b[N];
PII p[N];
void solve(){
cin >> n >> k;
int mx=-1;
priority_queue<PII, vector<PII>, greater<PII>> q;
for(int i=1;i<=n;i++){
cin >> a[i];
p[i].second=a[i];
mx=max(mx,a[i]);
}
for(int i=1;i<=n;i++){
cin >> b[i];
p[i].first=b[i];
q.push(p[i]);
}
int sum=0;
while(k>0){
sum+=k;
if(sum>=mx){
cout << "YES" << endl;
return ;
}
while(q.size()>0 && q.top().second<=sum ){
q.pop();
}
int res=q.top().first;
k-=res;
}
cout << "NO" << endl;
}
signed main(){
int t=1;
cin >> t;
while(t--){
solve();
}
}
C. Another Array Problem
题意:给定一个长度为n的数组a,可以执行以下操作任意次:选择两个位置 i ,j ,使[ai—aj]全部变为abs(ai-aj)。问可以得到的最大数组和。
思路:最优的情况下可以将每个数变为数组的最大值使其和最大,可以发现当(n>3)若最大值在最左\右侧时可以将数组中所有数变为最大值,而(n>4)时无论最大值在哪个地方都可将数组中所有数变为最大值(如[1,2,9,4] ->[1,1,9,4]->[0,0,9,4]->[9,9,9,4]->....[9,9,0,0]->[9,9,9,9]),故当n>4,答案为max*n,当n<4,枚举所有情况即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n;
int a[N];
void solve(){
cin >> n;
int mx=-1;
int sum=0;
for(int i=1;i<=n;i++){
cin >> a[i];
mx=max(mx,a[i]);
sum+=a[i];
}
if(n>3) {
int ans=mx * n;
cout << ans << endl;
return ;
}
else if(n==2){
int res=abs(a[1]-a[2])*2;
int ans=max(sum,res);
cout << ans << endl;
}
else{
if(a[1]==mx || a[3]==mx) { //最大值在两侧,答案就是mx*3
int ans=mx * 3;
cout << ans << endl;
return ;
}
int res1=max(abs(a[1]-a[2]),a[3]) * 3; //对于i=1,j=2操作,答案就是两侧的最大值*3
int res2=max(abs(a[2]-a[3]),a[1]) * 3; //对于i=2,j=3操作,答案就是两侧的最大值*3
int res3=abs(a[3]-a[1]) * 3; //对于i=1,j=3操作,答案就是abs(a[1]-a[3])*3;
int ans=max(max(sum,res1),max(res1,res2)); //输出最大值即可
cout << ans << endl;
}
}
signed main(){
int t=1;
cin >> t;
while(t--){
solve();
}
return 0;
}