Codeforces Round #710 (Div. 3)(题解)

传送门
在这里插入图片描述在这里插入图片描述题目大意:
已知按列排序的某个位置的数
求按行排序的相同位置的数

思路:
先计算给出的那个数按列排序的位置,然后在转化为按行排序的相同位置的数。

#include<bits/stdc++.h>
using namespace std;

#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

void slove()
{
	LL n,m,x;
	cin >> n >> m >> x;
	if(n == 1 || m == 1) {
		cout << x << endl; 
		return ;
	}
	LL l = x%n;
	if(l == 0) l = n;
	LL k = x/n;
	if(l != 0 && l != n) k++;
	cout << (l-1)*m+k << endl;
 } 

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
    }
    return 0;
}

传送门

在这里插入图片描述在这里插入图片描述题目大意:
将首尾的*转化为X,要求每两个X之间的距离小于K,求将星号转化为X的最小次数。

思路:
从前往后遍历一遍指针推动X的位置即可

#include<bits/stdc++.h>
using namespace std;

#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

void slove()
{
	int n,k;
	cin >> n >> k;
	string s;
	cin >> s;
	int cnt = 0,fre = 0,la = fre;
	for(int i = 0;i < s.length();++i){
		if(s[i] == '*' && cnt == 0){
			fre = i;cnt = 1;
		}
		else if(s[i] == '*'){
			if(i-fre > k){
				fre = la;
				cnt++;
			}
			la = i;
		}
		else if(s[i] == 'x') fre = i;
	}
	if(la != 0) cnt++;
	cout << cnt << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
    }
    return 0;
}

传送门
在这里插入图片描述在这里插入图片描述题目大意:
寻找最大公共子串

思路:
dp

#include<bits/stdc++.h>
using namespace std;

#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

int dp[30][30];

int getLCS(string s, string t)
{
    int result = 0;
    int sLength = s.length();
    int tLength = t.length();
    for (int i = 0; i < sLength; i++) {
        for (int k = 0; k < tLength; k++) {
            if (s[i] == t[k]) {
                if (i == 0 || k == 0) {
                    dp[i][k] = 1;
                } else {
                    dp[i][k] = dp[i - 1][k - 1] + 1;
                }
                result = max(dp[i][k], result);
            } else {
                dp[i][k] = 0;
            }
        }
    }
    return result;
}

void slove()
{
	string s,t;
	cin >> s >> t;
	cout << s.length()+t.length()-2*getLCS(s,t) << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
    }
    return 0;
}

传送门
在这里插入图片描述在这里插入图片描述题目大意:
两个不相同的数会相互抵消,求最后最少剩下几个数

思路:
求个数最多的数字的个数
如果个数大于一半2*ma - n
否则单数剩一个,双数剩0个

#include<bits/stdc++.h>
using namespace std;

#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

map<int,int> mp;

void slove()
{
	int n;
	cin >> n;
	mp.clear();
	int ma = 0;
	for(int i = 1,x;i <= n;++i){
		cin >> x;
		mp[x]++;
		ma = max(ma,mp[x]);
	}
	if(ma*2 <= n) 
	{
		if(n%2 == 0) cout << 0 << endl;
		else cout << 1 << endl; 
	}
	else cout << n-2*(n-ma) << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
    }
    return 0;
}

传送门
在这里插入图片描述在这里插入图片描述在这里插入图片描述题目大意:
给出一个序列第i个位置上的数字代表着原序列1~i的最大数
求原序列的最大序和最小序列

思路:
用数组来保存可能输出的数,序列中数字第一次出现就输出,
第二次出现就判断从前往后和从后往前输出确定序列
也可以使用二分,反向插数牛啊牛啊

#include<bits/stdc++.h>
using namespace std;

#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

set<int> s,s1;
int a[200020];
bool vis[200020];
vector<int> v;

void slove()
{
	int n;
	cin >> n;
	s.clear();
	s1.clear();
	memset(a,0,sizeof(a));
	memset(vis,0,sizeof(vis));
	for(int i = 1;i <= n;++i){
		cin >> a[i];
		s.insert(-i);
		s1.insert(i);
	}
	for(int i = 1;i <= n;++i){
		s.erase(-1*a[i]);
		s1.erase(a[i]);
	}
	for(int i = 1;i <= n;++i){
		if(!vis[a[i]]){
			cout << a[i] << " ";
			vis[a[i]] = 1;
		}
		else {
			cout << *s1.begin() << " ";
			s1.erase(*s1.begin());
		}
	}
	cout << endl;
	memset(vis,0,sizeof(vis));
	for(int i = 1;i <= n;++i){
		if(!vis[a[i]]){
			cout << a[i] << " ";
			vis[a[i]] = 1;
		}
		else {
			cout << -1**s.upper_bound(-a[i]) << " ";
			s.erase(*s.upper_bound(-a[i]));
		}
	}
	cout << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
    }
    return 0;
}

传送门
在这里插入图片描述在这里插入图片描述在这里插入图片描述原题大意:
杨辉三角采用二维标记。
奇数向左走偶数向右走
求将所给数字联通的最小修改步数

思路:
将数字排序。
相邻两个数字如果同差,同为奇数差则不变,否则加上行差
如果不同差,则将上一个根据相对关系,将上一个转化成1,1
再求转换次数

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
#define rep(i,a,b) for(int i = a;i <= n;++i)
const int maxn = 1e5+5;
int r[maxn*2],l[maxn*2];

bool isLeftArrow(int r,int c)
{
    return (r+c)%2 == 0;
}

bool isRightArrow(int r,int c)
{
    return (r+c)%2 == 1;
}


int calcDist(int r1,int c1,int r2,int c2)
{
    if(r1-c1 == r2-c2){
        return isRightArrow(r1,c1)?0:r2-r1;
    }
    r2 -= r1-1;
    c2 -= c1-1;
    if(isLeftArrow(r1,c1)){
        return (r2-c2)/2;
    }
    else return (r2-c2+1)/2;
}

void slove()
{
    int n;
    cin >> n;
    for(int i = 1;i <= n;++i) cin >> r[i];
    for(int i = 1;i <= n;++i) cin >> l[i];
    vector<pair<int,int>> pts;
    for(int i = 1;i <= n;++i) pts.emplace_back(r[i],l[i]);
    sort(pts.begin(),pts.end());
    int curC = 1,curR = 1;
    int res = 0;
    for(vector<pair<int,int>>::iterator it = pts.begin();it != pts.end();it++)
    {
        res += calcDist(curR,curC,it->first,it->second);
        curR = it->first;
        curC = it->second;
    }
    cout << res << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
        cout << endl;
    }
    return 0;
}

传送门
在这里插入图片描述在这里插入图片描述题目大意:
每一个字母都unique的情况下,求最大的序列

思路:
单调栈,入栈弹栈操作。
保证每一个字符都cnt=1

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
int cnt[30];
bool vis[30];
stack<char> st;
vector<char> v;

void slove()
{
    memset(cnt,0,sizeof(cnt));
    memset(vis,false,sizeof(vis));
    string s;
    cin >> s;
    int len = s.length();
    v.clear();
    for(int i = 0;i < len;++i) cnt[s[i]-'a']++;
    for(int i = 0;i < len;++i){
        while(!st.empty()){
            if(vis[s[i]-'a']) {
                cnt[s[i]-'a']--;
                break;
            }
            if(st.top() > s[i]){
                st.push(s[i]);
                vis[s[i]-'a'] = true;
                break;
            }
            else if(cnt[st.top()-'a'] > 1){
                vis[st.top()-'a'] = false;
                cnt[st.top()-'a']--;
                st.pop();
            }
            else {
                st.push(s[i]);
                vis[s[i]-'a'] = true;
                break;
            }
        }
        if(st.empty()) {
            st.push(s[i]);
            vis[s[i]-'a'] = true;
        }
    }
    while(!st.empty()){
        v.push_back(st.top());
        st.pop();
    }
    for(int i = v.size()-1;i >= 0;--i) cout << v[i];
    return ;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        slove();
        cout << endl;
    }
    return 0;
}

总结:
这场div3的难度整体不高,主要在思路理解上和一些简单算法
主要学习到了单调栈,和反向插数的思想
以及最大公共子串的dp思想

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值