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;
}
// 还是区间写法好理解😋
posted @ 2025-10-22 22:07  HS_fu3  阅读(14)  评论(1)    收藏  举报