CSP-S36
10.21
其实是 10.23 补的。
10.21 晚上想水 detect 结果就是边界问题被 detect 水了,10.22 才过,然后10.21就没写。
10.22 晚紧急回去选团员,回来 22:00 了,紧急贴了两张图上去。
(所以知道原因的xxx催啥呢,点名批评)
赤石场。
不是谁家好人 t1 概率啊?
t1
题解讲得挺明白,没必要再说了(神秘乱杀一切的做法太过于血腥暴力了)。

code
嘻嘻
#include <bits/stdc++.h>
#define ldb long double
using namespace std;
int x, y;
signed main()
{
freopen("island.in", "r", stdin);
freopen("island.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> x >> y;
ldb ans = 0;
for (int i = 1; i <= y; ++i)
ans += 1.0 / (2 * x + i);
for (int i = 1; i <= x; ++i)
ans += 1.0 / (2 * i - 1);
printf("%.16Lf\n", ans);
return 0;
}
t2
也是神秘题。
不是哥们你\(O(n^3)\) 的标算范围才 50 ?让折半搜过了???
赛时A的全是折半搜。
\(O(n^5)\) ,\(O(2^{\frac{n}{2}})\)都能过也是神了。
正解为dp。
设 \(dp_{i,j}\) ,表示到第 \(i\) 位,长度为 \(j\) 的字典序最大的串。
辅助数组 \(g_i\) 表示长度为 \(i\) 的字典序最大的串。
每次更新 \(g\) , \(dp\) 在 \(g\) 基础上累加即可。
鲜花:
字符串有重载后的小于号,就是按照字典序比较。
赛时试了“ccc” 与 "cca" 发现比较结果不对就以为不能比较,但赛后经Gon_Tata 大赦指点才发现对于 string 类型是有的,但直接写"ccc" 类型默认为char数组,故不能比较。
code
哈哈
#include <bits/stdc++.h>
using namespace std;
struct str
{
string s, t;
} f[100][100], g[100], ans;
string s, t;
inline str max(str S, str T)
{
string s = S.s + S.t, t = T.s + T.t;
// cerr << "S=" << s << " T=" << t << "\n";
return s > t ? S : T;
}
signed main()
{
freopen("xiao.in", "r", stdin);
freopen("xiao.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> s;
cin >> t;
int n = s.size();
s = " " + s, t = " " + t;
for (int i = 1; i <= n; ++i)
{
f[i][1].s += s[i], f[i][1].t += t[i];
for (int j = 2; j <= i; ++j)
{
f[i][j] = g[j - 1];
f[i][j].s += s[i], f[i][j].t += t[i];
}
for (int j = 1; j <= i; ++j)
g[j] = max(g[j], f[i][j]);
}
for (int i = 1; i <= n; ++i)
ans = max(ans, g[i]);
cout << ans.s + ans.t << "\n";
return 0;
}
t3

入手点是要发现题解里那两个性质。
发现后就可以直接双指针+线段树了。
注意双指针一定统计答案时一定要回移一位。
(线段树是为了更新区间信息以此快速判断是否合法,我也阐述不清过程,看代码+手模自行理解吧)。
code
呜呜
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 10;
int n;
int a[N], id[N];
struct tree
{
int l, r, laz, val;
} t[N << 2];
#define lid (id << 1)
#define rid (id << 1 | 1)
inline void pushdown(int id)
{
if (!t[id].laz)
return;
t[lid].laz += t[id].laz;
t[lid].val += t[id].laz;
t[rid].laz += t[id].laz;
t[rid].val += t[id].laz;
t[id].laz = 0;
}
void build(int id, int l, int r)
{
t[id].l = l, t[id].r = r;
if (l == r)
{
t[id].val = -l;
return;
}
int mid = (l + r) >> 1;
build(lid, l, mid);
build(rid, mid + 1, r);
t[id].val = max(t[lid].val, t[rid].val);
}
void update(int id, int l, int r, int val)
{
if (l <= t[id].l && t[id].r <= r)
{
t[id].laz += val, t[id].val += val;
return;
}
int mid = (t[id].l + t[id].r) >> 1;
pushdown(id);
if (mid >= l)
update(lid, l, r, val);
if (mid < r)
update(rid, l, r, val);
t[id].val = max(t[lid].val, t[rid].val);
}
signed main()
{
freopen("list.in", "r", stdin);
freopen("list.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n * 2 + 1; ++i)
cin >> a[i], id[a[i]] = min(i, 2 * n + 1 - i + 1);
int L = 1, R = 0, ans = 0;
build(1, 1, n + 1);
while (L <= 2 * n + 1 && R <= 2 * n + 1)
{
while (1)
{
if (R == 2 * n + 1)
break;
update(1, id[++R], n + 1, 1);
if (t[1].val > 0)
{
update(1, id[R--], n + 1, -1); // 一定要移回来
break;
}
if (R == 2 * n + 1)
break;
}
ans = max(R - L + 1, ans); // 然后加区间长度
update(1, id[L++], n + 1, -1);
}
cout << ans << "\n";
return 0;
}
// 还是区间写法好理解😋
本文来自博客园,作者:HS_fu3,转载请注明原文链接:https://www.cnblogs.com/HS-fu3/p/19159092

浙公网安备 33010602011771号