https://codeforces.com/contest/1546/problem/A
A. AquaMoon and Two Arrays
题意:给你一个数组a以及一个数组b,在一次操作中,你可以让a[i]+1且a[j]-1,i≠j。你可以操作很多次,直到a数组完全等于b数组,问你能不能完成操作,如果不能输出-1;如果可以,请输出最少操作次数。
思路:让a[i]与b[i]作比较,如果a[i]比较大那么就放出-1的操作里,如果相等直接跳过,如果a[i]比较小,放入+1的操作里。然后再判断+1的操作次数与-1的操作次数是否相同,如果不同那么我们就无法完成,否则输出操作次数以及分别输出每次操作的是哪两个序号。
代码:
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define hh 0x3f3f3f3f
const int MAXX=2e5+5;
using namespace std;
inline int read()
{
ll s=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}
return s*f;
}
int jian[100005],jia[100005],jian_,jia_,a[105],b[105];
void solve()
{
int n;
for(int i=1;i<=10000;i++)
{
jian[i]=0;
jia[i]=0;
}
cin>>n;
jian_=0,jia_=0;
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++)
{
if(a[i]==b[i])continue;
else if(a[i]>b[i])
{
int temp=a[i]-b[i];
while(temp)
{
jian[++jian_]=i;
temp--;
}
}
else
{
int temp=b[i]-a[i];
while(temp)
{
jia[++jia_]=i;
temp--;
}
}
}
if(jian_!=jia_)
{
cout<<"-1"<<endl;
}
else
{
cout<<jian_<<endl;
for(int i=1;i<=jian_;i++)
{
cout<<jian[i]<<" "<<jia[i]<<endl;
}
}
}
int main()
{
ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
https://codeforces.com/contest/1546/problem/B
B. AquaMoon and Stolen String
题意:给你长度为m的n串原字符串(n是奇数),然后再拿出n-1串字符串然后让他们两两随机交换位置,并给你。问:原字符串里的哪一串没被使用过。
思路:思考1-m位置他们再怎么交换位置都不变,因此我们可以用二维数组f[i][j]分别存他们的位置,i表示位置,j字符,不如abc,a存在f[1][97]的位置,b存在f[2][98]的位置,c存在f[3][99]的位置。。。
接下来是长度为m,n-1行的字符串,从存好的f[i][j]里取出来,取完后每个位置绝对会只剩下一个字符,这个字符就是对应的答案,输出这个就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define hh 0x3f3f3f3f
const int MAXX=2e5+5;
using namespace std;
inline int read()
{
ll s=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}
return s*f;
}
int f[MAXX][200];
char s[MAXX];
int n,m;
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++)//初始化
{
for(int j='a';j<='z';j++)
{
f[i][j]=0;
}
}
for(int i=1;i<=n;i++)//先输入原串
{
cin>>s+1;
for(int j=1;j<=m;j++)
{
f[j][s[j]]++;
}
}
for(int i=1;i<=n-1;i++)//删去原串
{
cin>>s+1;
for(int j=1;j<=m;j++)
{
f[j][s[j]]--;
}
}
for(int i=1;i<=m;i++)//输出剩下的字符串
{
for(int j='a';j<='z';j++)
{
if(f[i][j]==0)continue;
cout<<char(j);
break;
}
}
cout<<endl<<endl;
}
int main()
{
ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
https://codeforces.com/contest/1546/problem/C
C. AquaMoon and Strange Sort
题意:给你n个数,开始的时候每个数都是向右的,你可以进行任意次操作,交换a,b的位置,但是他们的方向也会变化,直到他们成为单调递增的序列。问你能不能在操作完成后他们的方向还是向右。
思路:我们不难发现奇数之间的交换或者是偶数之间的交换他们的方向都是不变的,比如,4,3,2,5(4,2都是奇数位;3,5都是偶数位),我们可以通过偶数位3作为中间媒介,交换4和2,因此,3、2、4都交换了两次他们的方向都没变。
那么可以用一个奇数位数组以及偶数位数组装他们:
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(i%2==0)ou[a[i]]++;
else ji[a[i]]++;
}
然后在通过sort排序,进行同上的操作,如果 奇数位或者偶数位的大小小于0,那么就说明排完序后的方向不可能都向右,反之成立。
代码:
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define hh 0x3f3f3f3f
const int MAXX=1e5+5;
using namespace std;
inline int read()
{
ll s=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}
return s*f;
}
int ji[MAXX],ou[MAXX],a[MAXX],n,pd;
void solve()
{
for(int i=1;i<=MAXX;i++)//初始化
{
ji[i]=0;ou[i]=0;
}
cin>>n;
pd=1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(i%2==0)ou[a[i]]++;//偶数位
else ji[a[i]]++;//奇数位
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
if(i%2==0)ou[a[i]]--;//偶数位
else ji[a[i]]--;//奇数位
if(ji[a[i]]<0||ou[a[i]]<0)//不成立的情况
{
pd=0;break;
}
}
if(pd)cout<<"YES\n";
else cout<<"NO\n";
}
int main()
{
ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}