首页 > 其他分享 >『模拟赛』NOIP2024加赛5

『模拟赛』NOIP2024加赛5

时间:2024-11-15 21:18:28浏览次数:1  
标签:ch int siz qr NOIP2024 加赛 now 模拟 define

Rank

反向挂分大王

image

A. 暴力操作(opt)

签,但是没有人签。

都想到了二分和更新 c 值,但是 c 多多少少没更到最优。

首先还是调和级数预处理,倒序取 min。然后考虑到超过 \(m\) 的也有可能产生更小的代价,因此 \(\mathcal{O(n)}\) 枚举一遍找到最小的 \(j\) 使 \(i\times j\gt m\),全部赋到 \(c_{m+1}\) 上,然后再倒序取一遍 min 就能更好的更新。

check 有 \(\mathcal{O(n)}\) 的双指针写法,我直接没改赛时的 \(\mathcal{O(n\log n)}\) 的二分,所以复杂度是 \(\mathcal{O(n\ln n+n\log^2n)}\) 的。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#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 pii pair<int, int>
#define ppp pair<pii, pii>
#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 = 5e5 + 5;
const int mod = 1e9 + 7;
ll n, m, k;
ll a[N], c[N];
namespace Wisadel
{
    bool Wck(int x)
    {
        ll ned = 0;
        fo(i, 1, n / 2 + 1) if(a[i] > x)
        {
            int l = 2, r = a[i] + 1;
            while(l < r)
            {
                int mid = (l + r) >> 1;
                if(a[i] / mid <= x) r = mid;
                else l = mid + 1;
            }
            ned += c[r];
            if(ned > k) return 0;
        }
        return 1;
    }
    short main()
    {
        freopen("opt.in", "r", stdin), freopen("opt.out", "w", stdout);
        n = qr, m = qr, k = qr;
        fo(i, 1, n) a[i] = qr;
        fo(i, 1, m) c[i] = qr;
        fo(i, 2, m) fo(j, 1, min(m / i, 1ll * i))
            c[i * j] = min(c[i * j], c[i] + c[j]);
        fu(i, m - 1, 1) c[i] = min(c[i], c[i + 1]);
        c[m + 1] = 1e9;
        fo(i, 2, m)
        {
            int zc = m / i + 1;
            c[m + 1] = min(c[m + 1], c[i] + c[zc]);
        }
        fu(i, m, 1) c[i] = min(c[i], c[i + 1]);
        sort(a + 1, a + 1 + n);
        int l = 0, r = a[n / 2 + 1];
        while(l < r)
        {
            int mid = (l + r) >> 1;
            if(Wck(mid)) r = mid;
            else l = mid + 1;
        }
        printf("%d\n", r);
        return Ratio;
    }
}
signed main(){return Wisadel::main();}
// Now there's only one thing I can do
// Fight until the end like I promised to

B. 异或连通(xor)

比较套路。

主要需要想到对询问建 trie 而不是边,那么容易发现一条边只会在 \(\log V\) 个子树中出现。按线段树分治的思想,直接在 trie 树上分治,找到对于每一个询问合法的线段存到点上,然后对 trie 树做一遍 dfs,过程中做启发式合并,回溯时撤销即可。

注意并查集不要路径压缩!复杂度 \(\mathcal{O(n\log n\log V)}\)。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#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 pii pair<int, int>
#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 = 1e5 + 5;
const int mod = 1e9 + 7;
int n, m, k, q;
struct rmm{int u, v, w;} e[N];
int que[N], pre[N];
namespace Wisadel
{
    ll fx[N], siz[N];
    int Wfind(int x)
    {
        if(x == fx[x]) return x;
        return Wfind(fx[x]);
    }
    void Wmerge(int u, int v)
    {
        u = Wfind(u), v = Wfind(v);
        if(u == v) return ;
        if(siz[u] < siz[v])
            fx[u] = v, siz[v] += siz[u];
        else fx[v] = u, siz[u] += siz[v];
    }
    int t[N * 20][2], tot;
    vector<pii> d[N * 20];
    vector<int> v[N * 20];
    ll ans[N * 20];
    void Wins(int x, int id)
    {
        int now = 0;
        fu(i, 30, 0)
        {
            int to = (x >> i) & 1;
            if(!t[now][to]) t[now][to] = ++tot;
            now = t[now][to];
        }
        pre[id] = now;
    }
    void Wupd(int x, int id)
    {
        int now = 0;
        fu(i, 30, 0)
        {
            int to = (x >> i) & 1, pd = (k >> i) & 1;
            if(pd)
            {
                if(t[now][to]) v[t[now][to]].P_B(id);
                now = t[now][to ^ 1];
            }
            else now = t[now][to];
            if(!now) return ;
        }
    }
    void Wdfs(int now, ll sum)
    {
        ans[now] = sum;
        for(int i : v[now])
        {
            int _ = Wfind(e[i].u), __ = Wfind(e[i].v);
            if(_ == __) continue;
            if(siz[_] < siz[__]) swap(_, __);
            ans[now] += siz[_] * siz[__];
            fx[__] = _, siz[_] += siz[__];
            d[now].P_B(M_P(_, __));
        }
        if(t[now][0]) Wdfs(t[now][0], ans[now]);
        if(t[now][1]) Wdfs(t[now][1], ans[now]);
        fu(i, d[now].size() - 1, 0)
        {
            pii zc = d[now][i];
            fx[zc.se] = zc.se;
            siz[zc.fi] -= siz[zc.se];
        }
    }
    short main()
    {
        freopen("xor.in", "r", stdin), freopen("xor.out", "w", stdout);
        n = qr, m = qr, q = qr, k = qr;
        fo(i, 1, n) fx[i] = i, siz[i] = 1;
        fo(i, 1, m) e[i].u = qr, e[i].v = qr, e[i].w = qr;
        fo(i, 1, q) que[i] = qr, Wins(que[i], i);
        fo(i, 1, m) Wupd(e[i].w, i);
        Wdfs(0, 0);
        fo(i, 1, q) printf("%lld\n", ans[pre[i]]);
        return Ratio;
    }
}
signed main(){return Wisadel::main();}
// Now there's only one thing I can do
// Fight until the end like I promised to

C. 诡异键盘(keyboard)

huge:你们上届学长只有三个改出来了

放最后改了,懂了大概思路。

赛时纯唐纯暴力做法打的 20pts 拿到了 70pts。

先做删串需要的同余最短路,然后建 trie 做 dp,具体不太会。

D. 民主投票(election)

好像是真正的签,不过为什么我需要卡常才能过?

首先需要求得树上最多票数最少 \(k\) 是多少,这个容易想到二分去做,设 \(f_i\) 为子树 \(i\) 在某个票数限制下需要向上贡献的票数,判断可行与否只需根据 \(f1=0\)。然后对于子树大小减一大于 \(k\) 点一定可行,小于 \(k\) 的一定不行,这两点都很显然。

关键在处理子树大小减一等于 \(k\) 的点。办法是以 \(k-1\) 为限制再 dp 一次。此时只有当前点的限制为 \(k\),则若 \(f_x=1\),那么解除限制后才满足 \(f_x=0\)。只有 \(x\) 到根路径上的点的 \(f\) 都为 0 且 \(f_1=1\) 时才合法,因为只有此时 \(f_x\) 限制加一才能解除 \(f_1\) 的限制。

时间复杂度 \(\mathcal{O(n\log n)}\),不知道为啥要卡常。

点击查看代码
// ubsan: undefined
// accoders
#include<bits/stdc++.h>
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#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 pii pair<int, int>
#define ppp pair<pii, pii>
#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 = 2e6 + 5;
const int mod = 1e9 + 7;
int n;
int hh[N], to[N], ne[N], cnt;
int siz[N], f[N];
bool ok[N];
namespace Wisadel
{
    inline void Wadd(int u, int v)
    {
        to[++cnt] = v;
        ne[cnt] = hh[u];
        hh[u] = cnt;
    }
    inline void Wdfs(int u, int fa)
    {
        siz[u] = 1;
        for(int i = hh[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            Wdfs(v, u);
            siz[u] += siz[v];
        }
    }
    inline void Wck(int u, int tar)
    {
        f[u] = 0;
        for(int i = hh[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            Wck(v, tar);
            f[u] += f[v] + 1;
        }
        if(f[u] <= tar) f[u] = 0;
        else f[u] -= tar;
    }
    inline void Wsol(int u)
    {
        if((u == 1 && f[u] != 1) || !f[u]) return ;
        if(f[u] == 1) ok[u] = 1;
        for(int i = hh[u]; i != -1; i = ne[i])
        {
            int v = to[i];
            Wsol(v);
        }
    }
    short main()
    {
        freopen("election.in", "r", stdin), freopen("election.out", "w", stdout);
        int T = qr;
        while(T--)
        {
            n = qr;
            cnt = 0;
            fill(hh + 1, hh + 1 + n, -1);
            fo(i, 2, n)
            {
                int x = qr;
                Wadd(x, i);
            }
            Wdfs(1, 0);
            int l = 1, r = n, ke = 0;
            while(l <= r)
            {
                int mid = (l + r) >> 1;
                Wck(1, mid);
                if(f[1] == 0) r = mid - 1, ke = mid;
                else l = mid + 1;
            }
            memset(ok+1, 0, sizeof(bool)*n);
            Wck(1, ke - 1);
            Wsol(1);
            fo(i, 1, n)
            {
                int zc = siz[i] - 1;
                if(zc > ke) putchar('1');
                else if(zc < ke) putchar('0');
                else printf("%d", ok[i]);
            }
            puts("");
        }
        return Ratio;
    }
}
signed main(){return Wisadel::main();}
// Now there's only one thing I can do
// Fight until the end like I promised to

邀请了 jijidawang 为特邀嘉宾帮助卡常,直接将一个 7000ms+ 的代码通过各种科技卡到了 accoder 上 1380ms。

jjdw 科技代码
// ubsan: undefined
// accoders
#include<bits/stdc++.h>
#define int unsigned
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#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 pii pair<int, int>
#define ppp pair<pii, pii>
#define fi first
#define se second
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
constexpr int Ratio = 0;
constexpr int N = 1e6 + 5;
const int mod = 1e9 + 7;
int n;
int siz[N], f[N], qwq[N];
int ok[N];
namespace Wisadel
{
    vector<int> g[N];
    inline void Wadd(int u, int v){g[u].emplace_back(v);}
    inline void Wck(int u, signed tar)
    {
        memset(f+1,0,sizeof(int)*n);
        #pragma GCC unroll 16
        for (int i=n; i>=2; i--)
        {
            f[i] = max<signed>((signed)f[i] - tar, 0);
            f[qwq[i]] += f[i] + 1;
        }
        f[1] = max<signed>((signed)f[1] - tar, 0);
    }
    inline void Wsol(int u)
    {
        if((u == 1 && f[u] != 1) || !f[u]) return ;
        if(f[u] == 1) ok[u] = 1;
        #pragma GCC unroll 2
        for (int v : g[u])
            Wsol(v);
    }
    inline __int32_t main()
    {
        freopen("election.in", "r", stdin), freopen("election.out", "w", stdout);
        int T = qr;
        while(T--)
        {
            n = qr;
            #pragma GCC unroll 32
            for(int i=1;i<=n;i++)g[i].clear();
            #pragma GCC unroll 8
            for(int i=1;i<=n;i++){ok[i]=0;siz[i]=1;}
            #pragma GCC unroll 32
            fo(i, 2, n)
            {
                qwq[i] = qr;
                Wadd(qwq[i], i);
            }
            #pragma GCC unroll 4
            fu(j, n, 2) siz[qwq[j]] += siz[j];
            int l = 1, r = n, ke = 0;
            while(l <= r)
            {
                int mid = (l + r) >> 1;
                Wck(1, mid);
                if(f[1] == 0) r = mid - 1, ke = mid;
                else l = mid + 1;
            }
            Wck(1, ke - 1);
            Wsol(1);
            #pragma GCC unroll 32
            fo(i, 1, n)
            {
                if(siz[i] - 1 > ke) putchar('1');
                else if(siz[i] - 1 < ke) putchar('0');
                else printf("%d", ok[i]);
            }
            puts("");
        }
        return Ratio;
    }
}
signed main(){return Wisadel::main();}
// Now there's only one thing I can do
// Fight until the end like I promised to

标签:ch,int,siz,qr,NOIP2024,加赛,now,模拟,define
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18548656

相关文章

  • 数据结构——栈和队列的模拟实现
    文章目录前言一、栈1.1概念与结构1.2栈的实现二、队列2.1概念与结构2.2队列的实现总结前言继上篇博客,已经把链表的有关习题完成,链表也已经收尾啦。今天来学习新的数据结构——栈和队列,fellowme一、栈1.1概念与结构栈:⼀种特殊的线性表,其只允许在固定......
  • NOIP2024加赛5
    喜欢每个包绑一个hack是吧。暴力操作(opt)容易发现答案具有单调性,考虑二分答案。还发现只需要处理\(1\sim\left\lceil\frac{n}{2}\right\rceil\)即可。发现如果\(c_{i}>c_{j}且i<j\),那么选\(j\)肯定更优。有\(\left\lfloor\frac{a}{bc}\right\rfloor=\left\lfloor\frac{\left\l......
  • NOIP2024加赛5
    NOIP2024加赛5题目来源:2023NOIPA层联测31\(T1\)HZTG5777.暴力操作(opt)\(40pts\)先将\(\{a\}\)升序排序。因为\(\left\lfloor\dfrac{\left\lfloor\frac{a}{b}\right\rfloor}{c}\right\rfloor=\left\lfloor\dfrac{a}{bc}\right\rfloor\),先钦定\(......
  • 2024.11.15 NOIP 模拟 - 模拟赛记录
    返乡(home)不给大样例是怕我找规律出答案吗?但是我还是找到规律了。题解说是结论题,但是这个结论即使观察小样例也很好猜(如果我是出题人就把样例打乱一下顺序)。首先考虑只有二维偏序时的最优放置方法:首先第一个数是不能重复的,因为一旦重复,第二个数无论怎么选,都会构成偏序;第二个......
  • NOIP2024模拟赛#21 总结
    坐牢3h+。赛时开T1,发现好唐啊,10min切了。过了全部大样例。开T2,现在是8:10。?现在是8:27,我怎么把T2大样例全过了。是不是太水了。我只是胡了一个贪心啊。开T3,现在是8:30。草,T1加样例了,做法假了。先不管T1了,先去看T3。感觉保证每次操作后都会满足对于\(i......
  • 241115 noip 模拟赛
    省流:\(90+100+25+10\)。T1题意:给定一个长为\(n\)的排列,定义一次操作为选出排列中至多\(4\)个不同的数,将它们任意重排,求最少操作次数让这个排列单调递增。\(n\leq10^6\)。找出排列的所有置换环,设环长为\(t_1,t_2,t_3,\cdots,t_m\),则答案为:\[\sum_{i=1}^m\lflo......
  • NOIP模拟赛 #11
    A一个\(R\timesC\)的矩阵\(A\),有\(N\)个位置已知,第\(i\)个为\(A_{r_i,c_i}=a_i\)。求是否存在一种填写剩下数字的方案,满足每个数字都非负且对于任意\(i,j(1\lei\leR-1,1\lej\leC-1)\)都有\(A_{i,j}+A_{i+1,j+1}=A_{i,j+1}+A_{i+1,j}......
  • [2024.11.15]NOIP 模拟赛
    赛后的思路永远比赛时清晰。赛时T1玩了一会发现\(a_3\sima_7\)一定是相邻的,所以只需要考虑两个数字即可。答案显然有单调性,所以考虑先二分\(a_2\),再二分\(a_1\)。两个二分的思路都很简单,第二个二分用lower_bound即可。第一个的话其实就是模拟lower_bound内置,赛时调......
  • CW 11.15 模拟赛记录
    看到说不按题目难度排序,先读下题初看\(\rm{T1}\)没什么思路\(\rm{T2}\)感觉像是\(\rm{dp}\),可能能多骗点?\(\rm{T3}\)又是计数\(\rm{T4}\)没思路感觉要寄,\(\rm{lhs}\)多半又要\(\rm{AK}\)\(\rm{T2}\)观察到这个类型的题比较熟,先开\(\rm{T2}\)简化题意......
  • 地面沉降数值模拟/三维地质建模数据处理技术应用
    地面沉降数值模拟实践技术应用与案例分析  目前,地面沉降问题是我国较为常见的环境地质问题,其巨大的破坏力严重影响城市建筑安全和交通轨道运行。围绕地面沉降的防控与治理,是工程地质、环境地质、轨道交通设计等相关技术人员十分关注的领域,而数值模拟技术是评估防控效果的有......