前言
想清楚之后再动手,写伪代码很重要!!!
点我进入比赛
a. Strange Table
题意
给定两个n * m 的矩阵, 一个按列排序,一个按行排序。现给你一个值,对应于列排列的矩阵的位置,输出按行排列的矩阵该位置的值。
思路
通过找规律可以发现:
列排序位置和值所对应的关系 =》
(
(
p
−
1
)
m
o
d
n
,
(
p
−
1
)
/
n
)
((p - 1) mod n, (p - 1) / n)
((p−1)modn,(p−1)/n)
行排序位置和值所对应的关系 = 》
p
=
x
∗
m
+
y
+
1
p = x * m + y + 1
p=x∗m+y+1
AC 代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << ENDL
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const int N = 30 + 10;
int main() {
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
ll n, m, x;
cin >> n >> m >> x;
cout << ((x - 1) % n) * m + (x - 1) / n + 1 << ENDL;
}
return 0;
}
b. Partial Replacement
题意
给定一个k 和一个长度为n且只包含"." 和 “*” 字符串, 现要用"z"去替换"*" , 字符串中第一个和最后一个"*"必须被替换,而且每次替换之后两个"z"之间的距离不能超过k。
思路
首先确定首尾字符的位置s和f,然后每次在[s + 1, s + k]中找最后一个*的位置更新s,答案自增即可。
AC 代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << ENDL
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const int N = 30 + 10;
int main() {
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
int n, k;
string str;
cin >> n >> k >> str;
int s = 0, f = 0;
_for(i, 0, n) if (str[i] == '*') {
s = i;
break;
}
For(i, n - 1, 0) if (str[i] == '*') {
f = i;
break;
}
int ans = 1 + (s != f);
while (s + k < f) {
For(i, s + k, s + 1) if (str[i] == '*') {
s = i;
ans++;
break;
}
}
cout << ans << ENDL;
}
return 0;
}
c. Double-ended Strings
题意
给定两个字符串a、b,每次可以对字符串删除前面或者后面的字符,求最少删除次数使得a 等于 b。
思路
删除之后得到相同的区域一定是a、b字符串中连续的一段,所以只要得到这一段的长度,然后用a和b的总长度减去两倍这段的长度即可得到答案。
AC 代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << ENDL
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const int N = 20 + 10;
char a[N], b[N];
int main() {
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> a >> b;
int sza = strlen(a), szb = strlen(b), sz = min(sza, szb);
int len = 0;
_for(i, 0, sza) _for(j, 0, szb) {
bool valid = true;
int k = 0;
for (k = 0; k < sz; ++k) {
if (i + k >= sza || j + k >= szb) break;
if (a[i + k] != b[j + k]) {
if (k > len) {
len = k;
valid = false;
}
break;
}
}
if (valid && k > len) len = k;
}
if (len) cout << sza + szb - 2 * len << ENDL;
else cout << sza + szb << ENDL;
}
return 0;
}
此处开始做不出来了。
d. Epic Transformation
题意
给定一个长度为n的整型数组,每次从中删除两个不同的数字,问:最后最小数组长度。
思路
这个题目卡在样例的最后一个数据点了,不知道怎么处理。
其实只要想到每次都去除数量最多的两个数这个贪心方法就做出来了。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << ENDL
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const int N = 100000 + 10;
set<int> num;
map<int, int> cnt;
int main() {
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
num.clear();
cnt.clear();
_for(i, 0, n){
int x;
cin >> x;
num.insert(x);
cnt[x]++;
}
priority_queue<int> h;
for (auto p : num) h.push(cnt[p]);
while (h.size() > 1) {
int a = h.top();
h.pop();
int b = h.top();
h.pop();
--a, --b;
n -= 2;
if (a) h.push(a);
if (b) h.push(b);
}
cout << n << ENDL;
}
return 0;
}
e. Restoring the Permutation
题意
给定一个数组q, 求符合该性质的 q i = m a x ( p 1 , p 2 , … , p i ) q_i =max(p_1,p_2,…,p_i) qi=max(p1,p2,…,pi)字典序最小的和字典序最大的原数组数组p。
思路
这题也是没有想周全就直接动手了,一测试数据点就错,所以说,写代码的时候先要在纸上写好伪代码,然后测试一下样例和自己出的样例,最后才是动手,不是高手就要想清楚之后再动手!
这个题目多看几组样例就可以发现:没个与前面一个数不同的数在最大或者最小数组中是不变的,这样就确定了几个不变的数,接下来就直接填数即可。
对于最小序列而言:两个已经确定的数之间放的一定是小于前一个数的最小可能取值。
这个从1开始一次取值即可。
对于最大序列而言:两个已经确定的数之间放的一定是小于前一个数的最大可能取值。
对于最大的来说,可以使用优先队列来维护可以有效值的最大值。
AC 代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << ENDL
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const int N = 200000 + 10;
int a[N], n;
bool st[N];
int main() {
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> n;
memset(st, 0, sizeof st);
_rep(i, 1, n) {
cin >> a[i];
if (a[i] != a[i - 1]) st[a[i]] = true;
}
int t = 1;
_rep(i, 1, n) if (a[i] != a[i - 1]) cout << a[i] << " ";
else {
while (st[t]) t++;
st[t] = true;
cout << t << " ";
}
cout << ENDL;
priority_queue<int> h;
_rep(i, 1, n) if (a[i] == a[i - 1]) cout << h.top() << " ", h.pop();
else {
cout << a[i] << " ";
_rep(j, a[i - 1] + 1, a[i] - 1) h.push(j);
}
cout << ENDL;
}
return 0;
}