Codeforces Round #699 (Div. 2)(A,B,C,D)
Solved
Solutions
A、Space Navigation
water.
代码:
string s;
map<char,int>mp;
int main()
{
int T;
cin>>T;
while(T--){
int x,y;
mp.clear();
mp['U']=0;
mp['R']=0;
mp['D']=0;
mp['L']=0;
cin>>x>>y;
cin>>s;
for(int i=0;i<s.size();i++){
mp[s[i]]++;
}
if((x>=0&&y>=0&&mp['R']>=x&&mp['U']>=y)||(x>=0&&y<0&&mp['R']>=x&&mp['D']>=abs(y))||(x<0&&y>=0&&mp['L']>=abs(x)&&mp['U']>=y)||(x<0&&y<0&&mp['L']>=abs(x)&&mp['D']>=abs(y))){
printf("YES\n");
}else{
printf("NO\n");
}
}
}
B、New Colony
题意:
有 \(n\) 座山,高度为 \(h[i]\) ,从起点开始一个个丢桶,遇到 \(h[i-1]<h[i]\) 的情况,则该桶停留在第 \(i-1\) 座山中,并且 \(h[i-1]=h[i-1]+1\),问你第 \(k\) 个桶在哪座山中(桶有可能直接到达终点,则输出 \(-1\))。
想法:
\(h[i]\) 数据范围小,我们直接暴力模拟放桶的过程即可。
代码:
int h[205];
int main()
{
int T;
int n,k;
cin>>T;
while(T--){
cin>>n>>k;
int now=0;
for(int i=1;i<=n;i++){
scanf("%d",&h[i]);
}
int sum=0;
int pos=-1;
int xx;
while(sum<k){
xx=1;
//cout<<sum<<endl;
for(int j=2;j<=n;j++){
if(h[j]>h[j-1]){
pos=j-1;
sum++;
h[j-1]++;
xx=0;
break;
}
//if(sum>=k)break;
}
//cout<<pos<<" "<<sum<<endl;
if(xx==1)break;
}
if(sum<k)pos=-1;
printf("%d\n",pos);
}
}
C、Fence Painting
题意:
有 \(n\) 面墙,最初颜色为 \(a[i]\) ,题目期望颜色为 \(b[i]\)。有 \(m\) 个画家,每个画家按给定顺序给某面墙画上颜色 \(c[i]\),颜色可以覆盖,但每个画家必须画一面墙。问是否有可能使每面墙都达到期望颜色。
想法:
- 首先我们看到画家有出场顺序,那么我们最需要考虑的是顺序后面的画家,因为后面的画家一定会对墙造成影响,而前面画家的影响可能会被后面的覆盖。
- 考虑第一种情况,期望颜色和初始颜色相同,只需要看最后出场的画家的颜色是否存在,若存在就在相同颜色的墙山画,前面的画家也在这面墙上画即可。否则就是 \(NO\)。
- 第二种情况,期望颜色和初始颜色不相同,那么我们把不相同的画的颜色和各个颜色的数量存储起来。对每个画家进行遍历,从后往前遍历,遇到该画家画的颜色是被需要的,则画在需要的墙上,否则画在这个画家后面的画家要画的墙上,因为这样子这个多余的颜色的影响就会被后面的画家的影响覆盖。
- 最后遍历所有墙,看是否符合即可。
代码:
int a[maxn],b[maxn];
int c[maxn];
int ans[maxn];
struct node{
int id;
int co;
};
vector<int>v[maxn];
vector<int>vv;
int num[maxn];
int num2[maxn];
int poss[maxn];
int main()
{
int T,n,m;
cin>>T;
while(T--){
vv.clear();
cin>>n>>m;
mem(poss,-1);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
num[i]=0;
num2[i]=0;
v[i].clear();
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
poss[b[i]]=i;
num2[b[i]]++;
}
for(int i=1;i<=m;i++){
scanf("%d",&c[i]);
}
for(int i=1;i<=n;i++){
if(a[i]!=b[i]){
v[b[i]].push_back(i);
vv.push_back(b[i]);
num[b[i]]++;
}
}
if(vv.size()>m){
printf("NO\n");
continue;
}
if(vv.size()>0)sort(vv.begin(),vv.end());
int siz=vv.size();
int k=1;
int sumn=0;
vector<int>have;
if(vv.size()>0){
for(int i=m;i>=1;i--){
//int pos=lower_bound(vv.begin(),vv.end(),c[i])-vv.begin();
//cout<<vv[pos]<<" "<<pos<<endl;
if(v[c[i]].size()<=0){
if(have.size()){
ans[i]=have[0];
}else if(num2[c[i]]){
ans[i]=poss[c[i]];
have.push_back(poss[c[i]]);
}else{
k=0;
break;
}
}else{
int nowsize=v[c[i]].size();
int xx=v[c[i]][nowsize-1];
have.push_back(xx);
ans[i]=xx;
v[c[i]].pop_back();
sumn++;
}
}
}else{
if(poss[c[m]]!=-1){
for(int i=1;i<=m;i++)ans[i]=poss[c[m]];
}else{
k=0;
}
}
if(sumn<vv.size())k=0;
/*
for(int i=1;i<=m;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
*/
if(k){
printf("YES\n");
for(int i=1;i<=m;i++){
printf("%d%c",ans[i]," \n"[i==m]);
}
}else{
printf("NO\n");
}
}
}
D、AB Graph
题意:
给你一幅 \(n\) 个点的完全图,这幅图的边权只有可能是 \(a\) 或 \(b\) 。问你能否在这幅图上找到长度为 \(m\) 的路径,使路径上的字母按顺序构成一个回文串(每个点和每条边可以经过多次)。
想法:
- 分类讨论。
- 1、m为奇数,可以发现如 \(ababa\)、\(aaaaa\) 都是回文,且边权只有可能是 \(a,b\),那么只需要在 \(1\) 号点和 \(2\) 号点之间不断走即可。
- 2、m为偶数,图上存在两点之间两条边权相同,那么只要这两条边之间相互走即可。
- 3、除去以上两种情况,我们考虑是否可以有三个点去构造,发现这样子三个点就可以,三元组 \(<x,y,z>\) 满足 \((x\rightarrow y)\) = \((y\rightarrow z)\),因为这个情况下已经除去上面两种情况,那么 \((z\rightarrow y)\) = \((y\rightarrow x)\)一定成立。
- 设 \(x\rightarrow y = b\)。那么 \(y\rightarrow z = b\),\(z\rightarrow y = a\), \(y\rightarrow x = a\)。
- 然后对于回文串长度的一半是偶数,那么 \(ababbaba\) 显然是满足的,那么对于前一半 \(abab\),从 \(y\) 开始,和 \(x\) 不断循环即可,后一半 \(baba\) 在 \(y\) 和 \(z\) 之间走即可。
- 对于回文串长度的一半是奇数,那么 \(abababa\)显然满足。对于前一半 \(aba\) ,从 \(x\) 开始,和 \(y\)不断循环,那么最后来到 \(y\) 点,然后 \(y\rightarrow z\) 得到中间的 \(b\),后一半 \(aba\) ,从 \(z\) 开始和 \(y\) 不断循环即可。
代码:
int n,m;
char mp[maxn][maxn];
int ans[maxn][3];
int main()
{
int T;
cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=n;i++){
ans[i][1]=-1;
ans[i][2]=-1;
};
for(int i=1;i<=n;i++){
getchar();
for(int j=1;j<=n;j++){
scanf("%c",&mp[i][j]);
if(i!=j)ans[i][mp[i][j]-'a'+1]=j;
}
}
int k1=0;
int kk[3];
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(mp[i][j]==mp[j][i]){
kk[1]=i;
kk[2]=j;
k1=1;
break;
}
}
if(k1)break;
}
if(k1){
cout<<"YES"<<endl;
for(int i=1;i<=m+1;i++){
printf("%d%c",kk[i%2+1]," \n"[i==m+1]);
}
continue;
}
if(m%2==1){
printf("YES\n");
for(int i=1;i<=m+1;i++){
printf("%c%c","12"[i%2==0]," \n"[i==m+1]);
}
continue;
}else{
if(n==2){
printf("NO\n");
continue;
}
int x,y,z;
int ok=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
if(ans[j][mp[i][j]-'a'+1]!=-1){
x=i;
y=j;
z=ans[j][mp[i][j]-'a'+1];
ok=1;
goto end;
}
}
}
end:;
if(!ok){
printf("NO\n");
continue;
}
printf("YES\n");
if((m/2)%2==0){
printf("%d",y);
for(int i=1;i<=m/2;i++){
if(i%2==1){
printf(" %d",x);
}else{
printf(" %d",y);
}
}
for(int i=1;i<=m/2;i++){
if(i%2==1){
printf(" %d",z);
}else{
printf(" %d",y);
}
}
}else{
printf("%d",x);
for(int i=1;i<=m/2;i++){
if(i%2==1){
printf(" %d",y);
}else{
printf(" %d",x);
}
}
for(int i=1;i<=m/2;i++){
if(i%2==1){
printf(" %d",z);
}else{
printf(" %d",y);
}
}
}
printf("\n");
}
}
return 0;
}
越自律,越自由