首页 > 其他分享 >『模拟赛』多校A层冲刺NOIP2024模拟赛15

『模拟赛』多校A层冲刺NOIP2024模拟赛15

时间:2024-10-29 20:59:56浏览次数:5  
标签:ch 15 int dep qr 模拟 fo NOIP2024 define

Rank

一般

image

A. 追逐游戏 (chase)

签,但是保龄。

上来发现情况好像是有限的,于是直接分讨,不过漏了 n 种情况,小样例水,大样例 vscose 自带的 compare 跑不出来,注销一遍之后甚至进度条都没了导致我以为过了,最后 10min 才发现(

赛后发现二分是可做的,但是倍增的巨大常数加上逆天评测速度导致在 accoder 上跑不动,于是又学了一个新的树剖维护的不用二分的做法,找到三点最深的 lca 然后再分讨求 k 级祖先就能少很多情况,复杂度是 \(\mathcal{O(n\log n)}\) 的。

二分倍增代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
typedef long long ll;
using namespace std;
#define lx ll
inline lx qr()
{
    char ch = getchar(); lx x = 0, f = 1;
    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
    return x * f;
}
#undef lx
#define qr qr()
#define pll pair<ll, ll>
#define fi first
#define se second
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 2e5 + 5;
const int mod = 998244353;
int n, q, st1, ed, st2;
int dfn[N], dt, st[30][N], lg[N], dep[N], fx[N][30];
int hh[N], to[N << 1], ne[N << 1], cnt;
namespace Wisadel
{
    inline int Wget(int u, int v){return dfn[u] < dfn[v] ? u : v;}
    inline void Wadd(int u, int v)
    {
        to[++cnt] = v;
        ne[cnt] = hh[u];
        hh[u] = cnt;
    }
    inline void Wdfs(int u, int fa)
    {
        dfn[u] = ++dt, st[0][dfn[u]] = fx[u][0] = fa;
        dep[u] = dep[fa] + 1;
        fo(i, 1, lg[dep[u]]) fx[u][i] = fx[fx[u][i - 1]][i - 1];
        for(int i = hh[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            if(v == fa) continue;
            Wdfs(v, u);
        }
    }
    inline int Wlca(int u, int v)
    {
        if(u == v) return u;
        if((u = dfn[u]) > (v = dfn[v])) swap(u, v);
        int d = lg[v - u++];
        return Wget(st[d][u], st[d][v - (1 << d) + 1]);
    }
    inline int Wqk(int u, int k)
    {
        int t = u;
        fu(i, lg[k], 0) if((k >> i) & 1) t = fx[t][i];
        return t;
    }
    inline int Wq(int u, int v, int lca, int k)
    {
        if(dep[u] - dep[lca] >= k) return Wqk(u, k);
        else return Wqk(v, dep[u] + dep[v] - 2 * dep[Wlca(u, v)] - k);
    }
    short main()
    {
        freopen("chase.in", "r", stdin), freopen("chase.out", "w", stdout);
        n = qr, q = qr;
        memset(hh, -1, sizeof hh);
        fo(i, 2, n) lg[i] = lg[i >> 1] + 1;
        fo(i, 1, n - 1)
        {
            int a = qr, b = qr;
            Wadd(a, b), Wadd(b, a);
        }
        Wdfs(1, 0);
        fo(i, 1, lg[n]) fo(j, 1, n - (1 << i) + 1)
            st[i][j] = Wget(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
        fo(i, 1, q)
        {
            st1 = qr, ed = qr, st2 = qr;
            int lca = Wlca(st1, ed), l = 0, r = dep[st1] + dep[ed] - 2 * dep[Wlca(st1, ed)];
            int a1 = dep[ed] + dep[st2] - 2 * dep[Wlca(ed, st2)], a2 = ed;
            while(l <= r)
            {
                int mid = (l + r) >> 1, zc = Wq(st1, ed, lca, mid);
                if(dep[zc] + dep[st2] - 2 * dep[Wlca(zc, st2)] <= mid) a1 = mid, a2 = zc, r = mid - 1;
                else l = mid + 1;
            }
            printf("%d %d\n", a1, a2);
        }
        return 0;
    }
}
signed main(){return Wisadel::main();}
分讨树剖代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
typedef long long ll;
using namespace std;
#define lx ll
inline lx qr()
{
    char ch = getchar(); lx x = 0, f = 1;
    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
    return x * f;
}
#undef lx
#define qr qr()
#define pll pair<ll, ll>
#define fi first
#define se second
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 2e5 + 5;
const int mod = 998244353;
int n, q, st1, ed, st2, ans;
int dfn[N], dt, dep[N], fx[N], siz[N], top[N], pre[N], son[N];
int hh[N], to[N << 1], ne[N << 1], cnt;
namespace Wisadel
{
    inline void Wadd(int u, int v)
    {
        to[++cnt] = v;
        ne[cnt] = hh[u];
        hh[u] = cnt;
    }
    inline void Wdfs1(int u, int fa)
    {
        fx[u] = fa, siz[u] = 1, dep[u] = dep[fa] + 1;
        for(int i = hh[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            if(v == fa) continue;
            Wdfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]]) son[u] = v;
        }
    }
    inline void Wdfs2(int u, int tp)
    {
        dfn[u] = ++dt, pre[dt] = u, top[u] = tp;
        if(son[u]) Wdfs2(son[u], tp);
        for(int i = hh[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            if(v == fx[u] || v == son[u]) continue;
            Wdfs2(v, v);
        }
    }
    inline int Wlca(int u, int v)
    {
        while(top[u] != top[v])
        {
            if(dep[top[u]] < dep[top[v]]) swap(u, v);
            u = fx[top[u]];
        }
        if(dep[u] > dep[v]) swap(u, v);
        return u;
    }
    inline int Wd(int u, int v){return dep[u] + dep[v] - 2 * dep[Wlca(u, v)];}
    inline int WLCA(int u, int v, int e)
    {
        int l1 = Wlca(u, v), l2 = Wlca(u, e), l3 = Wlca(v, e);
        return (dep[(dep[l1] > dep[l2] ? l1 : l2)] > dep[l3] ? (dep[l1] > dep[l2] ? l1 : l2) : l3);
    }
    inline int Wqk(int u, int k)
    {
        int t = dep[u] - k;
        while(dep[fx[top[u]]] >= t) u = fx[top[u]];
        return pre[dfn[u] - (dep[u] - t)];
    }
    inline int Wfind(int u, int v, int k)
    {
        int lca = Wlca(u, v);
        if(dep[u] - dep[lca] >= k) return Wqk(u, k);
        return Wqk(v, dep[u] + dep[v] - 2 * dep[lca] - k);
    }
    short main()
    {
        freopen("chase.in", "r", stdin), freopen("chase.out", "w", stdout);
        n = qr, q = qr;
        memset(hh, -1, sizeof hh);
        fo(i, 1, n - 1)
        {
            int a = qr, b = qr;
            Wadd(a, b), Wadd(b, a);
        }
        Wdfs1(1, 0), Wdfs2(1, 1);
        fo(i, 1, q)
        {
            st1 = qr, ed = qr, st2 = qr;
            int lca = WLCA(st1, ed, st2);
            int d1 = Wd(st2, lca), d2 = Wd(st1, lca), d3 = Wd(ed, lca);
            int nd = 0; ans = 0;
            if(d1 > d2) nd = d1 + d3, ans = ed, printf("%d %d\n", nd, ans);
            else nd = (d1 + d2 + 1) / 2, ans = Wfind(st1, st2, nd), printf("%d %d\n", nd, ans);
        }
        return Ratio;
    }
}
signed main(){return Wisadel::main();}

B. 统计

思维题。

\(\mathcal{O(\frac{n^2}{m})}\) 的做法是好想的,只有长度为 \(m\) 的倍数的区间才可能为合法区间,枚举一个端点即可。

正解是很优的,给每个数(值域上)赋一个权值,然后求前缀和,找这些前缀和是否存在差为 \([1,m]\) 权值和的倍数的,有的话显然就合法。为了方便可以使这个值为 0,具体做法是将 \(m\) 的权值设为负的 \([1,m-1]\) 的权值和,这样做后可以直接对前缀和 sort 一遍,然后简单记个相同的个数计数即可,复杂度 \(\mathcal{O(Tn\log n)}\)。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
typedef long long ll;
using namespace std;
#define lx ll
inline lx qr()
{
    char ch = getchar(); lx x = 0, f = 1;
    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
    return x * f;
}
#undef lx
#define qr qr()
#define pll pair<ll, ll>
#define fi first
#define se second
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 1e6 + 5;
const int mod = 998244353;
mt19937 myrand(chrono::high_resolution_clock::now().time_since_epoch().count());
int n, m;
int a[N];
ll v[N], sum[N], ans;
namespace Wisadel
{
    short main()
    {
        freopen("st.in", "r", stdin), freopen("st.out", "w", stdout);
        int T = qr;
        while(T--)
        {
            n = qr, m = qr, ans = 0;
            v[m] = sum[m] = 0;
            fo(i, 1, m - 1) v[i] = myrand(), v[m] -= v[i];
            fo(i, 1, n) a[i] = qr, sum[i] = sum[i - 1] + v[a[i]];
            sort(sum, sum + 1 + n);
            int zc = 1;
            fo(i, 1, n)
            {
                if(sum[i] != sum[i - 1]) zc = 0;
                ans += zc++;
            }
            printf("%lld\n", ans);
        }
        return Ratio;
    }
}
signed main(){return Wisadel::main();}

C. 软件工程

T3's examples are weaker than a three-year-old boy's ____

骗分:直接输出最长的 \(m-1\) 段,然后找剩下线段的交,实现好了可以直接过。

正解:设 \(f_{i,j}\) 为前 \(i\) 个分为 \(j\) 段的最大权值。首先可以考虑某个集合内的线段的交不为空的情况,此时对于一条线段,首先可以让它单独成为一个集合,也可以让它并到之前的某个集合里。可以按右端点排序,这样只用考虑左端点的事,状态转移方程为:

\[f_{i,j}=\max(f_{i-1,j-1}+len_i,f_{i-1,j}-\max(0,l_i-maxl)) \]

其中 \(maxl\) 为目前左端点的最大值,比较显然这是损失最小的转移方式。

当然还可能会有存在交集为空的集合,这个时候直接丢出一个装垃圾的集合,一条线段只有单独成为集合与扔到垃圾集合两种可能,转移很简单。

最终答案是二者的最大值。复杂度 \(\mathcal{O(n\log n)}\)。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
typedef long long ll;
using namespace std;
#define lx ll
inline lx qr()
{
    char ch = getchar(); lx x = 0, f = 1;
    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
    return x * f;
}
#undef lx
#define qr qr()
#define pll pair<ll, ll>
#define fi first
#define se second
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 5000 + 5;
const int mod = 998244353;
int n, m;
ll f[N][N], ans;
struct rmm{int l, r;} d[N];
namespace Wisadel
{
    inline bool cmp(rmm A, rmm B){return A.r < B.r;}
    short main()
    {// T3's examples are weaker than a three-year-old boy's ____
        freopen("se.in", "r", stdin), freopen("se.out", "w", stdout);
        n = qr, m = qr;
        fo(i, 1, n) d[i].l = qr, d[i].r = qr;
        sort(d + 1, d + 1 + n, cmp);
        fo(i, 1, m - 1) ans += d[i].r - d[i].l;
        memset(f, -0x3f, sizeof f);
        f[1][1] = d[1].r - d[1].l;
        int maxx = d[1].l;
        fo(i, 2, n)
        {
            fo(j, 1, min(i, m))
                f[i][j] = max(f[i - 1][j - 1] + d[i].r - d[i].l, f[i - 1][j] - max(0, d[i].l - maxx));
            maxx = max(maxx, d[i].l);
        }
        ans = f[n][m];
        memset(f, -0x3f, sizeof f);
        fo(i, 0, n) f[i][0] = 0;
        fo(i, 1, n) fo(j, 1, min(i, m)) f[i][j] = max(f[i - 1][j - 1] + d[i].r - d[i].l, f[i - 1][j]);
        printf("%lld\n", max(f[n][m - 1], ans));
        return 0;
    }
}
signed main(){return Wisadel::main();}

D. 命运的X

好像有类似的。丁真说是硬币游戏,外校说的啥忘了。

可以将随机过程看做 kmp 匹配的过程,题解说的很形象,挂一下:

image

然后推式子就很平凡了,最终答案为 \(m^n+\sum_{p\in P}\ m^p\),\(P\) 为 \(B\) 数组的 \(Border\) 集合,也就是 kmp 数组。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
typedef long long ll;
using namespace std;
#define lx ll
inline lx qr()
{
    char ch = getchar(); lx x = 0, f = 1;
    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
    return x * f;
}
#undef lx
#define qr qr()
#define pll pair<ll, ll>
#define fi first
#define se second
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 1e6 + 5;
const int mod = 998244353;
int n, m;
int a[N], kmp[N];
ll ans;
namespace Wisadel
{
    ll Wqp(ll x, int y)
    {
        ll res = 1;
        while(y)
        {
            if(y & 1) res = res * x % mod;
            x = x * x % mod;
            y >>= 1;
        }
        return res;
    }
    void Wpre()
    {
        int j = 0;
        fo(i, 2, n)
        {
            while(j && a[j + 1] != a[i]) j = kmp[j];
            if(a[j + 1] == a[i]) j++;
            kmp[i] = j;
        }
    }
    short main()
    {
        freopen("x.in", "r", stdin), freopen("x.out", "w", stdout);
        int T = qr;
        while(T--)
        {
            m = qr, n = qr;
            fo(i, 1, n) a[i] = qr;
            Wpre();
            ans = 0;
            int now = n;
            while(now) ans = (ans + Wqp(m, now)) % mod, now = kmp[now];
            printf("%lld\n", ans);
        }
        return 0;
    }
}
signed main(){return Wisadel::main();}

CSP 后第一场,因为假期缘故打的不是很好。

T1 唐氏没有人工比对,扫到第三行就能发现问题但到最后才发现还是因为突然想到少了种情况。T2 trick 就当长知识了,T3 骗分都没骗好,\(\mathcal{O(n)}\) 能做到的求交硬是吃了个 TLE。

赛时眼睛一直不舒服,中午睡一觉好了。

CSP 烂也就烂了,没法再改变什么,唯一能做的就是再坚持一个月,认真对待每一套题,少颓直到不颓,在 NOIP 这个最后的机会证明自己。


完结撒花~

没图了放库存,以后估计也不会再找了(真的吗
image

标签:ch,15,int,dep,qr,模拟,fo,NOIP2024,define
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18514358

相关文章

  • 省选前模拟赛记录
    日期类型ABCD总分小经验0820省选/互测赛\(\color{green}{数论分块/性质}\)\(\color{blue}{期望}\)\(\color{blue}{生成函数/多项式}\)16大样例/longlong0824省选/互测赛\(\color{green}{FWT}\)\(\color{green}{Ad-hoc}\)\(\color{blue}{数据结构优......
  • OpenGMS是什么?如何使用OpenGMS的建模与模拟工具(一)
    目录OpenGMS是什么?如何使用OpenGMS的建模与模拟工具(一)一、什么是OpenGMS1、OpenGMS网站 2、OpenGMS团队二、为什么我们需要OpenGMS1、地理模拟实验的局限性区域性限制了科研应用的效率2、外界对于OpenGMS的评价三、 OpenGMS的模型调用方法1、注册账号2、获取需要......
  • [57] (多校联训) A层冲刺NOIP2024模拟赛15
    A.追逐游戏一个非常暴力的想法是直接求出最短路径\(S\),然后对\(S\)上的点,比较\(dis_{s,S_i}\)和\(dis_{s',S_i}\)的大小,如果抓捕的人先到就符合条件实际上,这个符合条件的路径是单调的,即在最短路径上存在一个断点,断点靠近起点的一侧总不可达,靠近终点的一侧总是可达的证明......
  • LeetCode15:三数之和
    原题地址:.-力扣(LeetCode)题目描述给你一个整数数组 nums ,判断是否存在三元组 [nums[i],nums[j],nums[k]] 满足 i!=j、i!=k 且 j!=k ,同时还满足 nums[i]+nums[j]+nums[k]==0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复......
  • 十一月模拟赛总结
    10.29多校联测30+35+0+0=65菜就多练T1:题意:给定一棵以1为根的树,从节点1出发,如果当前节点有儿子没走过,可以花费对应边权的时间走到儿子,否则不花费时间走回父结点。每个点带权值,要求最小化到达节点时间乘点权总和。解:非常明确的贪心,对于子树内部最优路径必然确定,只要考虑先......
  • NOIP模拟赛 #2
    #1不想理会。A给定\(n\)个点和\(2n-3\)条边,这些边形成了一个凸\(n\)边形以及其三角剖分。你可以任意选择三个点,建立一个新的点以及其连接这三个点的边。最小化新建的点数,使得存在一种把最终的图拆分成两个边集无交的生成树的方案。通过交互来新建节点,并返回构造的方案......
  • 全国山洪径流模拟与洪水淹没危险性评价、GIS水文信息提取与分析、洪峰流量估算、洪水
    目录专题一:洪水淹没危险性评价方法及技术专题二:GIS水文信息提取与分析专题三:山洪径流模拟与洪峰流量估算、洪水频率分析专题四:【山洪、洪水】淹没模拟及水力学分析专题五:洪水风险制图及2024年典型洪水复盘GIS水文分析(ArcHydro、SpatialAnlysist等模块)是流域水文模拟......
  • macOS Sequoia 15.1 (24B83) 正式版 ISO、IPSW、PKG 下载
    macOSSequoia15.1(24B83)正式版ISO、IPSW、PKG下载iPhone镜像、Safari浏览器重大更新和AppleIntelligence等众多全新功能令Mac使用体验再升级请访问原文链接:macOSSequoia15.1(24B83)正式版ISO、IPSW、PKG下载查看最新版。原创作品,转载请保留出处。作者主页......
  • macOS Sequoia 15.1 (24B83) Boot ISO 原版可引导镜像下载
    macOSSequoia15.1(24B83)BootISO原版可引导镜像下载iPhone镜像、Safari浏览器重大更新和AppleIntelligence等众多全新功能令Mac使用体验再升级请访问原文链接:macOSSequoia15.1(24B83)BootISO原版可引导镜像下载查看最新版。原创作品,转载请保留出处。作者主......
  • NOIP 模拟赛:2024-10-23
    T1:游戏有\(n\)个关卡,编号\(1\simn\),编号\(i\)的关卡的难度是\(p_i\),其中\(p_1,p_2,\dots,p_n\)是\(1,2,\dots,n\)的一个排列。每一个关卡还定义了一个重要度\(d_i\),它的值等于其中前\(i\)个关卡中的难度最小值,即\(d_i=\min_{j=1}^ip_j\)。玩家需通关每个关......