# 2018 Multi-University Training Contest 5

### B - Beautiful Now

$$n$$最多为10位数，显然如果$$k\geq 10$$，我们直接贪心进行排序然后输出即可(注意前导零)。

Code
/*
* Author:  heyuhhh
* Created Time:  2020/5/7 14:02:54
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;

int a[10], b[10], pos[10], vis[10];

void run() {
int n, k;
cin >> n >> k;
int tot = 0;
while (n) {
a[tot++] = n % 10;
n /= 10;
}
reverse(a, a + tot);
if (k >= tot) {
sort(a, a + tot);
for (int i = 0; i < tot; i++) {
if (a[i] != 0) {
cout << a[i];
break;
}
}
for (int i = 0; i < tot; i++) {
if (a[i] == 0) {
cout << 0;
}
}
int cnt = 0;
for (int i = 0; i < tot; i++) {
if (a[i] != 0 && cnt) cout << a[i];
if (a[i] != 0) ++cnt;
}
cout << ' ';
reverse(a, a + tot);
for (int i = 0; i < tot; i++) cout << a[i];
cout << '\n';
return;
}
for (int i = 0; i < tot; i++) b[i] = i;
int ans1 = 2e9, ans2 = -1;
do {
if (a[b[0]] == 0) continue;
for (int i = 0; i < tot; i++) {
pos[b[i]] = i;
vis[i] = 0;
}
int t = 0;
for (int i = 0; i < tot; i++) if (!vis[i]) {
int x = i, len = 0;
while (!vis[x]) {
vis[x] = 1;
x = pos[x];
++len;
}
t += len - 1;
if (t > k) break;
}
if (t > k) continue;
int res = 0;
for (int i = 0; i < tot; i++) {
res = res * 10 + a[b[i]];
}
ans1 = min(ans1, res);
ans2 = max(ans2, res);
} while(next_permutation(b, b + tot));
cout << ans1 << ' ' << ans2 << '\n';
}

int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T; while(T--)
run();
return 0;
}


### G - Glad You Came

Code
/*
* Author:  heyuhhh
* Created Time:  2020/5/8 11:15:33
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5, M = 5e6 + 5;

unsigned int X, Y, Z;
unsigned int rng61() {
X ^= X << 11;
X ^= X >> 4;
X ^= X << 5;
X ^= X >> 14;
unsigned int tmp = X ^ Y ^ Z;
X = Y;
Y = Z;
Z = tmp;
return Z;
}

int lg[N];
void init() {
lg[2] = 1;
for (int i = 3; i < N; i++) lg[i] = lg[i >> 1] + 1;
}

int n, m;
int f[N][20];

void upd(int &x, int y) {
if (x < y) x = y;
}

void run() {
cin >> n >> m >> X >> Y >> Z;
for (int i = 1; i <= n; i++)
for (int j = 0; j < 20; j++)
f[i][j] = 0;
while (m--) {
int L = rng61() % n + 1, R = rng61() % n + 1, v = rng61() & ((1 << 30) - 1);
if (L > R) swap(L, R);
int d = lg[R - L + 1];
upd(f[L][d], v), upd(f[R - (1 << d) + 1][d], v);
}
for (int j = 19; j >= 1; j--) {
for (int i = 1; i + (1 << (j - 1)) <= n; i++) {
upd(f[i][j - 1], f[i][j]);
upd(f[i + (1 << (j - 1))][j - 1], f[i][j]);
}
}
ll ans = 0;
for (int i = 1; i <= n; i++) {
ans ^= 1ll * i * f[i][0];
}
cout << ans << '\n';
}

int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
init();
int T; cin >> T; while(T--)
run();
return 0;
}


### H - Hills And Valleys

• 考虑如果不存在翻转操作，其实就是一个比较简单的$$dp$$$$dp_{i,j}$$表示匹配了前$$i$$个字符，最后一个为$$j$$的方案数。但这个$$dp$$在有翻转操作存在时就不好处理，因为$$dp$$的第二维我们不好去转移。
• 我们可以将这个问题转化一下，就题目给定一个匹配串，然后会有一个模式串$$012...9$$，现在两个串进行匹配，注意模式串中一个字符可以匹配多次，问最长公共上升子序列。
• 转移的话$$dp_{i,j}=max\{dp_{i-1,j}+same(i,j),dp_{i,j-1}\}$$
• 那怎么处理翻转操作呢？这个时候其实就很好处理了，我们只需要翻转模式串即可，最后就形如$$012...xy(y-1)...x(y+1)(y+2)...9$$这个样子，然后类似求最长公共子序列即可。
• 因为我们还需要求翻转区间，所以我们还要记录一下状态中第一个$$y$$出现的位置，最后一个$$x$$出现的位置即可。

Code
/*
* Author:  heyuhhh
* Created Time:  2020/5/8 11:54:49
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5, M = 13;

int n;
int f[N][M], fl[N][M], fr[N][M];
int a[N], b[M], m;
char s[N];
int ans, l, r;

void dp(int L, int R) {
for (int i = 0; i <= m; i++) {
f[0][i] = 0;
fl[0][i] = fr[0][i] = -1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
f[i][j] = f[i - 1][j];
fl[i][j] = fl[i - 1][j];
fr[i][j] = fr[i - 1][j];
if (a[i] == b[j]) {
++f[i][j];
if (a[i] == R && fl[i][j] == -1) fl[i][j] = i;
if (a[i] == L) fr[i][j] = i;
}
if (f[i][j - 1] > f[i][j]) {
f[i][j] = f[i][j - 1];
fl[i][j] = fl[i][j - 1];
fr[i][j] = fr[i][j - 1];
}
}
}
if (L == 1 && R == 1) {
l = r = 1;
ans = f[n][m];
} else {
if (f[n][m] > ans && fl[n][m] != -1 && fr[n][m] != -1 && fl[n][m] < fr[n][m]) {
ans = f[n][m];
l = fl[n][m], r = fr[n][m];
}
}
}

void run() {
cin >> n >> (s + 1);
for (int i = 1; i <= n; i++) {
a[i] = s[i] - '0';
}
m = 0;
for (int i = 0; i < 10; i++) {
b[++m] = i;
}
dp(1, 1);
for (int i = 0; i < 10; i++) {
for (int j = i + 1; j < 10; j++) {
m = 0;
for (int k = 0; k <= i; k++) b[++m] = k;
for (int k = j; k >= i; k--) b[++m] = k;
for (int k = j; k < 10; k++) b[++m] = k;
dp(i, j);
}
}
cout << ans << ' ' << l << ' ' << r << '\n';
}

int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T; while(T--)
run();
return 0;
}

posted @ 2020-05-09 13:21  heyuhhh  阅读(180)  评论(0编辑  收藏  举报