A. Image
模拟
#include<bits/stdc++.h>
using namespace std;
map<int,int>mp;
int main()
{
int T;cin>>T;
while(T--){
mp.clear();char a,b,c,d;cin>>a>>b>>c>>d;
mp[a]++;mp[b]++;mp[c]++;mp[d]++;
int sum=0;int r=4;
for (auto i:mp){
if(i.second==1&&r!=1){sum++;r--;}
if(i.second==2&&r!=2){sum++;r-=2;}
}
cout<<sum<<endl;
}
return 0;
}
题解是用set做的,更简单
#include<bits/stdc++.h>
using namespace std;
set<char>mp;
int main()
{
int T;cin>>T;
while(T--){
mp.clear();
char a,b,c,d;cin>>a>>b>>c>>d;
mp.insert(a);mp.insert(b);mp.insert(c);mp.insert(d);
cout<<(int)mp.size()-1<<endl;
}
return 0;
}
B. Deadly Laser
思路:首先无论怎么走,最小步数都是n+m-2,所以就是看激光覆盖的范围阻挡了路
有4种阻挡方式
1.拦住左下角 2.拦住右上角 3.拦住竖的 4.拦住横的
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;cin>>T;
while(T--){
int n,m,sx,sy,d;cin>>n>>m>>sx>>sy>>d;
if(m-sy<=d&&n-sx<=d||sy-1<=d&&sx-1<=d||sy-1<=d&&m-sy<=d||sx-1<=d&&n-sx<=d)
cout<<-1<<'\n';
else cout<<(n+m-2)<<'\n';
}
return 0;
}
C. Min-Max Array Transformation
注意点:数据范围是2e5,数组开小了会TLE
思路:
首先找最小的数组很好找,只要找恰好等于它的数字就可以了;
找最大数的话,看样例的规律,从n-1到0的话,如果 a[i] 大于b[i-1],这代表b[i-1]不可能是a[i]以及之前的数的和,所以从b[i-1]开始作为新的开头;否则因为前面b[i]都是大于a[i]的,没有限死,所以都可以选最大的
#include<bits/stdc++.h>
using namespace std;
int a[200005],b[200005],d[200005];
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while(T--){
int n;cin>>n;
int minn=999999999;int maxx=0;
for(int i=0;i<n;i++)cin>>a[i];for(int i=0;i<n;i++)cin>>b[i];
int l=0;
for(int i=0;i<n;i++){while(b[l]<a[i])l++;cout<<b[l]-a[i]<<" ";}
cout<<'\n';
l=n-1;
for(int i=n-1;i>=0;i--){d[i]=b[l]-a[i];if(a[i]>b[i-1])l=i-1;}
for(int i=0;i<n;i++)cout<<d[i]<<" ";cout<<'\n';
}
return 0;
}
从前往后找的道理差不多
#include<bits/stdc++.h>
using namespace std;
int a[200005],b[200005];
int main()
{
ios::sync_with_stdio(0);cin.tie(0);
int T;cin>>T;
while(T--){
int n;cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<n;i++)cin>>b[i];
int l=0;
for(int i=0;i<n;i++){while(b[l]<a[i])l++;cout<<b[l]-a[i]<<" ";}
cout<<'\n';l=0;
for(int i=0;i<n;i++){
l=max(l,i);while(a[l+1]<=b[l]&&l+1<n)l++;cout<<b[l]-a[i]<<" ";
}
cout<<'\n';
}
return 0;
}
D. Maximum AND
题意:有数列a和b,数列c是通过a异或b得出的,最后的value是数组c的与运算,求最大的value
思路:
方法一:
已知最后的value的最高位一定是c数组的每个都有的1的那个位置
每个都有1的位置是由a数组的1和b数组的0做成的(或者a数组的0和b数组的0做成的)
那么可以设一个数x,x与上每一个a[i],其结果cc是只有x上有1的位数和a[i]同时有1的位数才能显示出来
x与上每一个(取反的b[i]),其结果dd是只有x上有1的位数和(取反的b[i])同时有1的位数才能显示出来
如果cc和dd能过一一相等,代表了a[i]的1和b[i]的0能够一一对应(同时也是a[i]的0和b[i]的1一一对应了)
所以check时只要判断cc和dd是否相等就可以了
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[100005];int b[100005];int n;
int c[100005];int d[100005];
bool check(int x){
for(int i=1;i<=n;i++)c[i]=a[i]&x;
for(int i=1;i<=n;i++)d[i]=(~b[i])&x;
sort(c+1,c+1+n);sort(d+1,d+1+n);
for(int i=1;i<=n;i++){
if(c[i]!=d[i])return 0;
}
return 1;
}
signed main()
{
int T;cin>>T;
while(T--){
int coun=0;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
int res=0;
for(int i=31;i>=0;i--){
if(check(res|(1<<i)))res=res|((1<<i));
}
cout<<res<<'\n';
}
return 0;
}
方法二(并查集)
如果某一位a的1部分和b的0部分配对,如果个数不对就continue
如果对了的话就从那一部分再把a的1部分和b的0部分配对,如果个数不对接着continue
但我还没看……