Codeforces Round 479 (Div. 3)

本文详细解析了六个编程竞赛中的题目,涉及减法错误处理、字符串操作、二分查找、数列规律、环形结构和连续子序列,提供了解题思路和代码示例。
摘要由CSDN通过智能技术生成

这一场div3整体比较简单注意细节即可

目录

A. Wrong Subtraction

B. Two-gram

C. Less or Equal

D. Divide by three, multiply by two

E. Cyclic Components

F. Consecutive Subsequence


A. Wrong Subtraction

按照题目意思直接模拟操作次数即可

void solve(){
   
    cin>>n>>m;
    while(m--){
    	int t=n%10;
    	if(t) n--;
    	else n/=10;
    }
    cout<<n<<endl;
    return ;
}

B. Two-gram

按照字符串也是直接模拟即可

void solve(){
   
    map<string,int> mp;
    cin>>n;
    string s; cin>>s;
    string ans=" ";
    for(int i=1;i<n;i++){
    	string now;
    	now+=s[i-1];
    	now+=s[i];
    	mp[now]++;
    	if(mp[now]>mp[ans]){
    		ans=now;
    	}
    }
    cout<<ans<<endl;
    return ;
}

C. Less or Equal

我们可以发现答案是具有二分性质的如果一个数越大少于他的数只会变多所以考虑二分即可

void solve(){
   
    cin>>n>>m;
    vector<int> a(n);
    for(auto&v:a) cin>>v;
    sort(a.begin(),a.end());
    
    auto check = [&](int x){
    	int cnt=0;
    	for(auto&v:a) cnt+=v<=x;
    	return cnt;
    };
    
    int l=1,r=1e9;
    while(l<r){
    	int mid=l+r+1>>1;
    	if(check(mid)<=m) l=mid;
    	else r=mid-1;
    }
    cout<<(check(l)==m ? l : -1)<<endl;
    return ;
}

D. Divide by three, multiply by two

每一个数的前后数一定是一一对应的所以可以直接记录,然后我们考虑求倒着用下一位记录前一位这样就可以直接倒推(同时注意开longlong)

void solve(){
   
    cin>>n;
    vector<LL> a(n);
    map<LL,LL> cnt,pre;
    for(auto&v:a){
    	cin>>v;
    	cnt[v]++;
    }
    LL last;
    for(auto&v:a){
    	if(cnt.count(2*v)) pre[2*v]=v;
    	else if(v%3==0 && cnt.count(v/3))pre[v/3]=v;
    	else last=v;
    }
    vector<LL> ans;
    ans.push_back(last);
    while(pre.count(last)){
    	last=pre[last];
    	ans.push_back(last);
    }
    reverse(ans.begin(),ans.end());
    for(auto&v:ans) cout<<v<<' ';
    cout<<endl;
    return ;
}

E. Cyclic Components

我们发现一个环上的一定都是每个点都是有两个子节点,这就是这题的性质然后dfs即可

bitset<N> st;
bool ok;
void dfs(int u){
	
	st[u]=true;
	if(g[u].size()!=2) ok=false;
	for(auto&v:g[u]){
		if(!st[v])dfs(v); 
	}
}

void solve(){
   
    cin>>n>>m;
    while(m--){
    	int a,b; cin>>a>>b;
    	g[a].push_back(b);
    	g[b].push_back(a);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
    	if(!st[i]){
    		ok=true;
    		dfs(i);
    		ans+=ok;
    	}
    }
    cout<<ans<<endl;
    return ;
}

F. Consecutive Subsequence

这一题是一个简单的dp记录方案我们考虑直接用map来存储,用pre表示上一个节点,idx当前位置,dp表示数量即可表示所有的信息从前完后的去找每一个数的x-1是否存在是一定合理的

void solve(){
   
    cin>>n;
    vector<int> a(n+5);
    map<int,int> dp,pre,idx;
    for(int i=1;i<=n;i++) cin>>a[i];
    
    int pos=1;
    for(int i=1;i<=n;i++){
    	dp[a[i]]=1;
    	idx[a[i]]=i;
    	if(dp.count(a[i]-1)){
    		pre[i]=idx[a[i]-1];
    		dp[a[i]]=dp[a[i]-1]+1;
    		if(dp[a[i]]>dp[a[pos]]) pos=i;
    	}
    }
    vector<int> ans;
    ans.push_back(pos);
    while(pre[pos]!=0){
    	ans.push_back(pre[pos]);
    	pos=pre[pos];
    }
    cout<<ans.size()<<endl;
    reverse(ans.begin(),ans.end());
    for(auto&v:ans) cout<<v<<' ';
    cout<<endl;
    return ;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值