A. Image
一共四个字符,每次最多变一个或者两个相同字符到其他字符去,枚举所有情况就好了。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
int num[maxn];
void solve(){
char a;
map<char,int>mm;
for(int i = 1;i<=4;i++){
cin>>a;
mm[a]++;
}
if(mm.size()==4){
cout<<3<<endl;
}
else if(mm.size()==3){
cout<<2<<endl;
}
else if(mm.size()==2){
cout<<1<<endl;
}
else if(mm.size()==1){
cout<<0<<endl;
}
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int t;
cin>>t;
while(t--)
solve();
}
B. Deadly Laser
贪心一下,相当于这个陷阱覆盖的范围是一个斜着的正方形。一共两种走法,L和倒L,如果两种走法都走不了说明无论怎么走都会遇到这个陷阱
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
int num[maxn];
int n,m,sx,sy,d;
int j = 0;
void solve(){
j = 1;
cin>>n>>m>>sx>>sy>>d;
for(int i = 1;i<=n;i++){
if(abs(i-sx)+abs(1-sy)<=d){
j = 0;
break;
}
}
for(int i = 1;i<=m;i++){
if(abs(n-sx)+abs(i-sy)<=d){
j = 0;
break;
}
}
if(j){
cout<<n+m-2<<endl;
return;
}
j = 1;
for(int i = 1;i<=m;i++){
if(abs(1-sx)+abs(i-sy)<=d){
j = 0;
break;
}
}
for(int i = 1;i<=n;i++){
if(abs(i-sx)+abs(m-sy)<=d){
j = 0;
break;
}
}
if(j){
cout<<n+m-2<<endl;
return;
}
cout<<-1<<endl;
return;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int t;
cin>>t;
while(t--)
solve();
}
C. Min-Max Array Transformation
最基础的匹配方式肯定是a[i]对b[i]这样子匹对上去,如果要找最小的,那么a[i]肯定要匹配b中比i下标小或者相等的位置。
直接用lowerbound就可以了,因为都是按顺序匹配的,找到a[i]和b[j]匹配后,j前面的仍然一一对应,i-j的部分让a[o]和b[o+1]匹配即可
更大的就不能这样使用,同理a[i]要匹配b中大于等于i的下标,同样构造
但是我们不能保证a[o]和b[o-1]一定能匹配上,因此我们用双指针即可。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
int num[maxn];
int a[maxn],b[maxn];
void solve(){
int n;
cin>>n;
for(int i = 1;i<=n;i++)
cin>>a[i];
for(int i = 1;i<=n;i++)
cin>>b[i];
for(int i = 1;i<=n;i++){
int pos = lower_bound(b+1,b+n+1,a[i])-b;
cout<<b[pos]-a[i]<<" ";
}
cout<<endl;
int j = 1;
for(int i = 1;i<=n;i++){
j = max(i,j);
while(b[j]>=a[j+1]&&j<n)
j++;
cout<<b[j]-a[i]<<" ";
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int t;
cin>>t;
while(t--)
solve();
}
D. Maximum AND
ai和bi可以重新分组,也就意味着其实是让ai和bi进行配对,而这样的配对要尽可能让每一个ci的高位都为1,即优先第一高位为1,然后是第二第三。暴力处理一下
#include <bits\stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int a[maxn],b[maxn];
#define ll long long
void solve() {
int n;
cin>>n;
for(int i = 1;i<=n;i++){
cin>>a[i];
}
for(int i = 1;i<=n;i++){
cin>>b[i];
}
int ans = 0;
for(int i= 29;i>=0;i--){
map<int,int>m;
int now = ans|(1<<i); //判断这样分组能不能满足前面确定的答案
int ok = 1;
for(int j = 1;j<=n;j++){
m[a[j]&now]++; //这步感觉蛮巧妙的,首先把低位全部归0不考虑,高位如果之前给出的答案是0也归0不考虑
//如果是1的话就保留a中对应的0 1部分,在分组的时候进行考虑
}
for(int j = 1;j<=n;j++){
int hh = (now&b[j])^now; //先&去掉不用考虑的部分,然后利用异或a^b =c a^c = b的性质看看能不能成功分组
if(m.count(hh)){
m[hh]--;
if(m[hh]==0)
m.erase(hh);
}
else{
ok = 0;
break;
}
}
if(ok)
ans = now;
}
cout<<ans<<endl;
}
int main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
}