题解:P6661 [POI 2019/2020 R1] Pomniejszenie / 削减
为了让构造出来的数
我们可以先处理出
若
计算出剩余操作数
如果计算出的
后缀的比较结果也预处理即可。设
如果
这时若
当
但这时我们又会发现冲突,即当
若是不操作
实现很简单,考虑清楚即可。
void process_pre_and_suf() {
pre[0] = 0;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + (a[i] != b[i]);
}
suf[n + 1] = 0;
for (int i = n; i; i--) {
if (a[i] > b[i])
suf[i] = 0;
else if (a[i] < b[i])
suf[i] = 1;
else
suf[i] = suf[i + 1];
}
}
bool check(int pos) {
if (pre[pos - 1] > k)
return 0;
int remain = k - pre[pos - 1];
if (remain > n - pos + 1)
return 0;
if (remain == 0) {
if (suf[pos])
return 1;
return 0;
}
if (a[pos] == b[pos] - 1) {
if (remain <= n - pos)
return 1;
if (a[pos] == '0')
return 0;
}
if (b[pos] == '0')
return 0;
return 1;
}
同样合法的情况,让
int get_pos() {
for (int i = n; i; i--) {
if (check(i))
return i;
}
return 0;
}
根据对应情况,我们只要注意
当
从高位到低位,所有数位能变成
void process_string(string &c, int pos, int remain) {
for (int i = pos; i <= n; i++) {
c[i] = a[i];
if (a[i] == '9')
continue;
if (remain > 0) {
c[i] = '9';
remain--;
}
}
if (remain == 0)
return;
for (int i = n; i >= pos; i--) {
if (a[i] == '9') {
c[i] = '8';
remain--;
if (remain == 0)
return;
}
}
assert(remain > 0);
}
string construst_ans(int pos) {
string c = b;
int remain = k - pre[pos - 1];
if (remain == 0) {
assert(suf[pos]);
for (int i = pos; i <= n; i++) {
c[i] = a[i];
}
return c;
}
if (a[pos] == b[pos] - 1) {
if (remain <= n - pos) {
c[pos] = a[pos];
process_string(c, pos + 1, remain);
return c;
}
assert(a[pos] != '0');
c[pos] = a[pos] - 1;
remain--;
process_string(c, pos + 1, remain);
return c;
}
assert(b[pos] != '0');
c[pos] = b[pos] - 1;
remain--;
process_string(c, pos + 1, remain);
return c;
}
单次时间复杂度为
Code
#include <iostream>
#include <cassert>
#include <string>
using namespace std;
const int N = 1e5 + 5;
int t;
string a, b;
int n, k;
void read() {
cin >> a >> b;
cin >> k;
n = a.size();
a = '?' + a;
b = '?' + b;
}
int pre[N];
bool suf[N];
void process_pre_and_suf() {
pre[0] = 0;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + (a[i] != b[i]);
}
suf[n + 1] = 0;
for (int i = n; i; i--) {
if (a[i] > b[i])
suf[i] = 0;
else if (a[i] < b[i])
suf[i] = 1;
else
suf[i] = suf[i + 1];
}
}
bool check(int pos) {
if (pre[pos - 1] > k)
return 0;
int remain = k - pre[pos - 1];
if (remain > n - pos + 1)
return 0;
if (remain == 0) {
if (suf[pos])
return 1;
return 0;
}
if (a[pos] == b[pos] - 1) {
if (remain <= n - pos)
return 1;
if (a[pos] == '0')
return 0;
}
if (b[pos] == '0')
return 0;
return 1;
}
int get_pos() {
for (int i = n; i; i--) {
if (check(i))
return i;
}
return 0;
}
void process_string(string &c, int pos, int remain) {
for (int i = pos; i <= n; i++) {
c[i] = a[i];
if (a[i] == '9')
continue;
if (remain > 0) {
c[i] = '9';
remain--;
}
}
if (remain == 0)
return;
for (int i = n; i >= pos; i--) {
if (a[i] == '9') {
c[i] = '8';
remain--;
if (remain == 0)
return;
}
}
assert(remain > 0);
}
string construst_ans(int pos) {
string c = b;
int remain = k - pre[pos - 1];
if (remain == 0) {
assert(suf[pos]);
for (int i = pos; i <= n; i++) {
c[i] = a[i];
}
return c;
}
if (a[pos] == b[pos] - 1) {
if (remain <= n - pos) {
c[pos] = a[pos];
process_string(c, pos + 1, remain);
return c;
}
assert(a[pos] != '0');
c[pos] = a[pos] - 1;
remain--;
process_string(c, pos + 1, remain);
return c;
}
assert(b[pos] != '0');
c[pos] = b[pos] - 1;
remain--;
process_string(c, pos + 1, remain);
return c;
}
int main() {
cin >> t;
while (t--) {
read();
process_pre_and_suf();
int pos = get_pos();
if (!pos) {
cout << "-1\n";
continue;
}
string ans = construst_ans(pos);
for (int i = 1; i <= n; i++)
cout << ans[i];
cout << '\n';
}
return 0;
}