2018 Multi-University Training Contest 5
Contents
A. Always Online
Unsolved.
B.Beautiful Now
Solved.
题意:
给出一个
每次可以将
思路:
很明显有一种思路,对于最小值,尽可能把小的放前面,对于最大值,尽可能把打的放前面。
但是如果有多个最小数字或者最大数字会无法得出放哪个好,因此 BFS 一下即可。
Code
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 10;
struct node {
int num, idx, step;
node() {}
node(int num, int idx, int step) : num(num), idx(idx), step(step) {}
};
int n, k;
int cnt;
int arr[maxn];
int BFS1() {
queue<node> q;
q.push(node(n, cnt, 0));
int ans = INF;
while (!q.empty()) {
node now = q.front();
q.pop();
ans = min(ans, now.num);
if (now.step == k)
continue;
if (now.idx == 1)
continue;
int tmp = now.num;
cnt = 0;
while (tmp) {
arr[++cnt] = tmp % 10;
tmp /= 10;
}
int Min = now.idx;
for (int i = now.idx - 1; i >= 1; --i) {
if (arr[i] == arr[now.idx])
continue;
if (arr[i] == 0 && now.idx == cnt)
continue;
if (arr[i] < arr[Min])
Min = i;
}
if (Min == now.idx) {
q.push(node(now.num, now.idx - 1, now.step));
} else {
for (int i = now.idx - 1; i >= 1; --i) {
if (arr[i] == arr[Min]) {
swap(arr[i], arr[now.idx]);
tmp = 0;
for (int j = cnt; j >= 1; --j) {
tmp = tmp * 10 + arr[j];
}
q.push(node(tmp, now.idx - 1, now.step + 1));
swap(arr[i], arr[now.idx]);
}
}
}
}
return ans;
}
int BFS2() {
queue<node> q;
q.push(node(n, cnt, 0));
int ans = -INF;
while (!q.empty()) {
node now = q.front();
q.pop();
ans = max(ans, now.num);
if (now.step == k)
continue;
if (now.idx == 1)
continue;
int tmp = now.num;
cnt = 0;
while (tmp) {
arr[++cnt] = tmp % 10;
tmp /= 10;
}
int Max = now.idx;
for (int i = now.idx - 1; i >= 1; --i) {
if (arr[i] == arr[now.idx])
continue;
if (arr[i] > arr[Max])
Max = i;
}
if (Max == now.idx) {
q.push(node(now.num, now.idx - 1, now.step));
} else {
for (int i = now.idx - 1; i >= 1; --i) {
if (arr[i] == arr[Max]) {
swap(arr[i], arr[now.idx]);
tmp = 0;
for (int j = cnt; j >= 1; --j) {
tmp = tmp * 10 + arr[j];
}
q.push(node(tmp, now.idx - 1, now.step + 1));
swap(arr[i], arr[now.idx]);
}
}
}
}
return ans;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d %d", &n, &k);
int tmp = n;
cnt = 0;
while (tmp) {
cnt++;
tmp /= 10;
}
k = min(k, cnt - 1);
int ans1 = BFS1();
int ans2 = BFS2();
printf("%d %d\n", ans1, ans2);
}
return 0;
}
C. Call It What You Want
Unsolved.
D. Daylight
Unsolved.
E. Everything Has Changed
Solved.
题意:
求多个圆的周长并
思路:
对于不想交和内含的直接 continue,相切的直接相加。
对于相交的可以减去大圆上的弧长,加上小圆的弧长。
Code
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const double eps = 1e-8;
int sgn(double x) {
if (fabs(x) < eps)
return 0;
else
return x > 0 ? 1 : -1;
}
struct Point {
double x, y;
Point() {}
Point(double _x, double _y) {
x = _x;
y = _y;
}
double distance(Point p) {
return hypot(x - p.x, y - p.y);
}
} P;
int n;
double R, r;
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d %lf", &n, &R);
double ans = 2 * R * PI;
for (int i = 1; i <= n; ++i) {
scanf("%lf %lf %lf", &P.x, &P.y, &r);
double dis = P.distance(Point(0.0, 0.0));
if (sgn(dis - (r + R)) >= 0)
continue;
else if (sgn(dis - (R - r)) < 0)
continue;
else if (sgn(dis - (R - r)) == 0) {
ans += 2 * PI * r;
continue;
}
double arc1 = (R * R + dis * dis - r * r) / (2.0 * R * dis);
arc1 = 2 * acos(arc1);
double arc2 = (r * r + dis * dis - R * R) / (2.0 * r * dis);
arc2 = 2 * acos(arc2);
ans -= R * arc1;
ans += r * arc2;
}
printf("%.10f\n", ans);
}
return 0;
}
F. Fireflies
Unsolved.
G. Glad You Came
Upsolved.
题意:
思路:
线段树,维护最大最小值 + 剪枝,因为数据随机才可以这样做。
Code
#include <bits/stdc++.h>
using namespace std;
#define N 5000010
#define M 100010
#define ui unsigned int
#define ll long long
int t, n, m;
ui x, y, z, w;
ui f[N << 2];
ui MOD = (ui)1 << 30;
ui rng61() {
x = x ^ (x << 11);
x = x ^ (x >> 4);
x = x ^ (x << 5);
x = x ^ (x >> 14);
w = x ^ y ^ z;
x = y;
y = z;
z = w;
return z;
}
struct SEG {
ui lazy[M << 2], Max[M << 2], Min[M << 2];
void Init() {
memset(lazy, 0, sizeof lazy);
memset(Max, 0, sizeof Max);
memset(Min, 0, sizeof Min);
}
void pushup(int id) {
Max[id] = max(Max[id << 1], Max[id << 1 | 1]);
Min[id] = min(Min[id << 1], Min[id << 1 | 1]);
}
void pushdown(int id) {
if (!lazy[id])
return;
lazy[id << 1] = lazy[id];
Max[id << 1] = lazy[id];
Min[id << 1] = lazy[id];
lazy[id << 1 | 1] = lazy[id];
Max[id << 1 | 1] = lazy[id];
Min[id << 1 | 1] = lazy[id];
lazy[id] = 0;
}
void update(int id, int l, int r, int ql, int qr, ui val) {
if (Min[id] >= val)
return;
if (l >= ql && r <= qr && Max[id] < val) {
lazy[id] = Max[id] = val;
return;
}
pushdown(id);
int mid = (l + r) >> 1;
if (ql <= mid)
update(id << 1, l, mid, ql, qr, val);
if (qr > mid)
update(id << 1 | 1, mid + 1, r, ql, qr, val);
pushup(id);
}
int query(int id, int l, int r, int pos) {
if (l == r)
return Max[id];
pushdown(id);
int mid = (l + r) >> 1;
if (pos <= mid)
return query(id << 1, l, mid, pos);
else
return query(id << 1 | 1, mid + 1, r, pos);
}
} seg;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d%u%u%u", &n, &m, &x, &y, &z);
for (int i = 1; i <= 3 * m; ++i) f[i] = rng61();
seg.Init();
for (int i = 1, l, r, v; i <= m; ++i) {
l = f[3 * i - 2] % n + 1;
r = f[3 * i - 1] % n + 1;
v = f[3 * i] % MOD;
if (l > r)
swap(l, r);
seg.update(1, 1, n, l, r, v);
}
ll res = 0;
for (int i = 1; i <= n; ++i) res ^= (ll)seg.query(1, 1, n, i) * (ll)i;
printf("%lld\n", res);
}
return 0;
}
H. Hills And Valleys
Upsolved,
题意:
给出一个长为
思路:
也就是说,可以存在这样一段:
我们知道,如果不可以翻转,求最长上升子序列的话,我们可以将原串和模式串
那么翻转的话,我们通过枚举翻转的区间
Code
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define INF 0x3f3f3f3f
int t, n, m, a[N], b[20];
int dp[N][20], tl[N][20], tr[N][20], res, l, r, ql, qr;
void solve() {
for (int i = 1; i <= m; ++i) dp[0][i] = 0, tl[0][i] = -1, tr[0][i] = -1;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
dp[i][j] = dp[i - 1][j];
tl[i][j] = tl[i - 1][j];
tr[i][j] = tr[i - 1][j];
if (a[i] == b[j]) {
++dp[i][j];
if (j == ql && tl[i][j] == -1)
tl[i][j] = i;
if (j == qr)
tr[i][j] = i;
}
if (j > 1 && dp[i][j - 1] > dp[i][j]) {
dp[i][j] = dp[i][j - 1];
tl[i][j] = tl[i][j - 1];
tr[i][j] = tr[i][j - 1];
}
}
if (ql == 1 && qr == 1) {
res = dp[n][m];
l = 1;
r = 1;
} else if (dp[n][m] > res && tl[n][m] != -1 && tr[n][m] != -1) {
res = dp[n][m];
l = tl[n][m];
r = tr[n][m];
}
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
res = 1, l = 1, r = 1;
for (int i = 1; i <= n; ++i) scanf("%1d", a + i);
for (int i = 1; i <= 10; ++i) b[i] = i - 1;
m = 10;
ql = 1, qr = 1;
solve();
for (int i = 1; i < m; ++i)
for (int j = i + 1; j <= 10; ++j) {
m = 0;
for (int pos = 1; pos <= i; ++pos) b[++m] = pos - 1;
ql = m + 1;
for (int pos = j; pos >= i; --pos) b[++m] = pos - 1;
qr = m;
for (int pos = j; pos <= 10; ++pos) b[++m] = pos - 1;
solve();
// for (int i = 1; i <= m; ++i) printf("%d%c", b[i], " \n"[i == m]);
}
printf("%d %d %d\n", res, l, r);
}
return 0;
}
I. Innocence
Unsolved.
J. Just So You Know
Unsolved.
K. Kaleidoscope
Unsolved.
L. Lost In The Echo
Unsolved.
Last update: March 28, 2022
Created: March 28, 2022
Created: March 28, 2022