AtCoder Regular Contest 154(A-D)

A - Swap Digit (atcoder.jp)

        (1)题目大意

                给你两个数字,你可以交换第i位上的数位,问你最后答案的最小值是多少。

         (2)解题思路

                考虑贪心思路,直接把小的丢一边,大的丢一边,相乘肯定是最小。

         (3)代码实现

#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
using namespace std;
const int N = 2e5 + 10;
char s[N],t[N];
using ll = long long;
const ll mod = 998244353;
void solve()
{
    int n;
    scanf("%d",&n);
   	scanf("%s%s",s+1,t+1);
   	rep(i,1,n) if(s[i]<t[i]) swap(s[i],t[i]);
   	ll num1=0,num2=0;
   	rep(i,1,n) num1=num1*10+(s[i]-'0'),num1%=mod;
   	rep(i,1,n) num2=num2*10+(t[i]-'0'),num2%=mod;
   	printf("%lld\n",(num1*num2)%mod);
}
int main()
{
    int T = 1;
    // cin >> T;
    while(T --) solve();
    return 0;
}

B - New Place (atcoder.jp)

        (1)题目大意

                给你两个长度为N的字符串S和T,你可以每次擦除S的第一个然后插入到任意位置。

                现在问你如果可以把S变成T,那么最小次数是多少,否则输出-1。

         (2)解题思路

                考虑把每一个位置都放入对应的字母set中,然后从后往前贪心匹配,若当前S[i]!=T[i],那么就需要从set中找到一个最靠前的字母T[i],如果找不到直接输出-1,如果找到了,发现你这个位置已经被拿过了,那么说明你这个位置的字符处于未被安置状态,则不会对答案产生贡献,否则你需要减去你之前那个拿到过的最大位置作为当前对答案的贡献。

         (3)代码实现

#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
using namespace std;
const int N = 2e5 + 10;
char s[N],t[N];
set<int>st[30];
void solve()
{
    int n;
    scanf("%d",&n);
    scanf("%s%s",s+1,t+1);
    int ans=0,j=n;
    rep(i,1,n) st[s[i]-'a'].insert(i);
    set<int>vis;
    per(i,n,1) {
    	if(s[j]==t[i]){
    		j--;
    		continue;
    	}
    	if(st[t[i]-'a'].size()==0){
    		printf("%d",-1);
    		return;
    	}
    	auto it=st[t[i]-'a'].begin();
    	auto it2=vis.upper_bound(*it);
    	if(vis.size()==0) ans+=*it;
    	else {
    		if(it2==vis.end()) --it2;
    		ans+=max(0,*it-*it2); 
    	}
    	st[t[i]-'a'].erase(it);
		vis.insert(*it);
    }
    printf("%d",ans);
}
int main()
{
    int T = 1;
    // cin >> T;
    while(T --) solve();
    return 0;
}

C - Roller (atcoder.jp)

        (1)题目大意

                给你一个长度为N的A和B数组,对于A数组你可以把A[i]替换成A[i+1],问你最后能不能把A变成B。

         (2)解题思路

                分类讨论

                1.若A原本等于B,输出Yes

                2.若A不等于B,且B的B[i]!=B[i+1]的有N对,则输出No

                3.直接枚举B循环左移,若存在A和B不匹配的次数小于N,则答案是Yes,否则是No

         (3)代码实现

#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
using namespace std;
const int N = 2e5 + 10;
void solve()
{
    int n;
    cin>>n;
    vector<int>A(n),B(n);
    rep(i,0,n-1)cin>>A[i];
    rep(i,0,n-1)cin>>B[i];
    if(A==B){
        cout<<"Yes"<<endl;
        return;
    }
    int cnt=0,ans=0;
    rep(i,0,n-2)if(B[i]!=B[i+1])cnt++;
    cnt+=B[n-1]!=B[0];
    if(cnt==n){
        cout<<"No"<<endl;
        return;
    }
    rep(i,0,n-1){
        B.push_back(B[0]);
        B.erase(B.begin());
        int num=0;
        rep(j,0,n-1)while(num<n&&B[j]!=A[num])num++;
        if(num<n){
            ans=1;
            break;
        }
    }
    if(ans) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T = 1;
    cin >> T;
    while(T --) solve();
    return 0;
}

D - A + B > C ? (atcoder.jp)

        (1)题目大意

                题目说有一个序列,你每次可以问A[i]+A[j]是否大于A[k],若大于返回Yes,否则返回No,问你是否可以在25000次内知道这个序列是什么。

         (2)解题思路

                首先,我们可以通过问N次问出来最小的那个位置在哪,问出来最小那个位置后,因为最小的是1,我们就可以快排确定其他数在什么位置了。

         (3)代码实现

                

#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
using namespace std;
const int N = 2e5 + 10;
int ans[N],loc[N];
bool ask(int i,int j,int k)
{
	cout<<"? "<<i<<' '<<j<<' '<<k<<endl;
	string s;
	cin>>s;
	return s[0]=='Y';
}
void solve()
{
    int n,mi=1,cur=2;
    cin>>n;
    set<int>st;
    rep(i,2,n) if(ask(mi,mi,i))mi=i;
    rep(i,1,n) st.insert(i);
    loc[1]=mi;
    st.erase(mi);
    rep(i,2,n) loc[i]=*st.begin(),st.erase(st.begin());
    stable_sort(loc+2,loc+1+n,[&](int x,int y){
        return ask(y,loc[1],x);
    });
    rep(i,1,n) ans[loc[i]]=i;
    cout<<"! ";
    rep(i,1,n) cout<<ans[i]<<' ';
    cout<<endl;
}
int main()
{
    int T = 1;
    // cin >> T;
    while(T --) solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值