11.26 CW 模拟赛 赛时记录

看题#

也是给他绑上 Subtask 了, 这我骗鸡毛分啊

感冒也是非常难受, 但是事已至此, 先读题吧


题目背景好看爱看

T1#

图论题, 好玩

T2#

大概也是不会做, 再说

T3#

难绷, 考虑高档暴力

T4#

这个肯定是暴力都难打


今天也是 30min+1h+15min+1h15min

T1#

先分析题意,

给定一张无重边, 无环的无向图
求加若干边之后, 图中最长链能达到多长

首先发现最后的图一定包含了全部的 n 个点, 因为如果不包含点 i , 那么选上点 i 之后, 最长的链一定会变得更长

容易的, 我们发现原图应该是一个森林, 那么我们需要把原图中的森林连接起来, 使得最长链最长, 符合直觉的, 我们应该去连接每颗树的直径

那么好, 这题结束了


首先读入是显然的, 对于每一个连通块, 两遍 dfs 求直径的两端

对于第 i 个连通块, 我们考虑将 i1 连通块的右侧 (这里的左右人为指定) , 和 i 的左侧连接起来, 对于 i=1/n 情况特殊处理

T2#

只过了 25min , 冲冲冲

T1 多半是大众分, 当然我多半拿不到大众分就是了 (确实没拿到)


转化题意

对于序列 s , 找出一段区间 [L,R] , 使得区间长度至少为 k 的前提下, 令所有数的 gcdg , 求 g×i=LRsimax

题意其实给的很清楚了, 不太需要转化

区间长是 106 级别的, 不好处理

暴力的做法是, 考虑对于一个固定的 R , 我们向前走, 记录 值和 gcd , 可以做到 O(n2) 的时间复杂度, 30pts

我们还需要优化, 这里优化的点很明确, 我们需要利用之前的计算结果, 不能再次重复计算

但是并不好利用之前的计算结果, 考虑神秘优化

注意到当右端点确定, gcd 的趋势是单调不增, 我们考虑预处理出所有 gcd 的变化区间的最左侧点, 只考虑最左端点即可, 期望上是 O(nn) 的, 可以拿到 60pts


一会再回来想一想

对于右端点的每一次拓张, 我们向左枚举到第一个值为当前 si 因数的最左侧点, 中间的全部都要并过来, 即在栈中弹出, 如果左边没有因数, 弹出完了之后插入一个 1 , 特别的, 判断一下 si 和当前栈头的关系, 看 si 是否需要单开区间

这个可以拿栈处理

T3#

转化题意

对于序列 s , 找出多少个区间 [L,R] 满足其中有一半以上的元素相同

对于 Subtask1,2 , O(n2logn) 算法可以解决

对于 Subtask3 ,

我们先预处理出两种数在区间中的出现次数的差出现次数的前缀和, 然后就简单了

代码#

没有好实现的, 按分值打

T1#

写的差不多, 看看会不会挂

#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e5 + 20;

#define FILE_IO

int n, m;

class Graph_Class
{
private:

public:
    /*并查集*/
    struct DSU_struct
    {
        int fa[MAXN];
        void fa_init() { for (int i = 1; i <= n; i++) fa[i] = i; }

        int find(int x) {
            return fa[x] = (x == fa[x]) ? x : find(fa[x]);
        }

        void merge(int u, int v) {
            int fa_u = find(u), fa_v = find(v);
            fa[fa_v] = fa_u;
        }
    } DSU;

    struct node
    {
        int to;
        int next;
    } Edge[MAXN << 1];
    int Edge_cnt = 0;
    int head[MAXN];
    void Edge_init() { for (int i = 1; i <= m * 2; i++) Edge[i].next = -1; }
    void head_init() { for (int i = 1; i <= n; i++) head[i] = -1; }
    void addedge(int u, int v) {
        Edge[++Edge_cnt].to = v;
        Edge[Edge_cnt].next = head[u];
        head[u] = Edge_cnt;
    }
} Graph;

class Sol_Class
{
private:
    int dist[MAXN];
    void dfs1(int Now, int fa, int d) {
        dist[Now] = d;
        for (int i = Graph.head[Now]; ~i; i = Graph.Edge[i].next) {
            int NowTo = Graph.Edge[i].to;
            if (NowTo == fa) continue;

            dfs1(NowTo, Now, d + 1);
        }
    }

    int CalcD(int NowTree) {
        for (int i = 1; i <= n; i++) {
            if (Graph.DSU.find(i) == NowTree) {
                dfs1(i, -1, 1);
                break;
            }
        }

        int Root = -1, maxdis = 0;
        for (int i = 1; i <= n; i++) {
            if (Graph.DSU.find(i) != NowTree) continue;
            if (dist[i] > maxdis) maxdis = dist[i], Root = i;
        }

        memset(dist, 0, sizeof(dist));
        dfs1(Root, -1, 1);

        Root = -1, maxdis = 0;
        for (int i = 1; i <= n; i++)
        {
            if (Graph.DSU.find(i) != NowTree) continue;
            if (dist[i] > maxdis) maxdis = dist[i], Root = i;
        }

        return maxdis;
    }

public:
    bool Treevis[MAXN];
    int Ans = 0;
    /*分割森林, 计算直径*/
    void solve()
    {
        for (int i = 1; i <= n; i++) {
            int NowTree = Graph.DSU.find(i);
            if (Treevis[NowTree]) continue;

            Ans += CalcD(NowTree);
            Treevis[NowTree] = true;
        }

        printf("%lld", Ans);
    }
} Sol;

signed main()
{
#ifdef FILE_IO
    freopen("chariot.in", "r", stdin);
    freopen("chariot.out", "w", stdout);
#endif

    scanf("%lld %lld", &n, &m);
    Graph.DSU.fa_init();
    Graph.head_init();
    Graph.Edge_init();
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%lld %lld", &u, &v);
        Graph.addedge(u, v), Graph.addedge(v, u);
        Graph.DSU.merge(u, v);
    }

    Sol.solve();

    return 0;
}

T2#

稍微复杂, 看运气了, 话说我今天 luogu 都没打卡

优化方法可能是错的, 跑不过大样例, 只能留在后面看看能骗多少

#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e6 + 20;

#define FILE_IO

int n, k;
int h[MAXN];
int Sum[MAXN];

class Subtask_3
{
private:
    /*栈*/
    struct node {
        int Pos;
        int Val;
    } ;
    struct Stack_struct
    { 
        node Stack[MAXN];
        int tp = 0;

        bool empty() {
            return tp == 0;
        }

        void pop() {
            tp--;
        }

        void push(node x) {
            Stack[++tp] = x;
        }

        node top() {
            return Stack[tp];
        }
    } S;

public:

/*处理*/
    void solve()
    {
        int Ans = 0;
        for (int i = 1; i <= n; i++)
        {
            /*处理 gcd 左端点*/
            while (!S.empty()) {
                node Now = S.top();
                if (h[i] % Now.Val == 0) break;
                S.pop();
            }

            if (S.empty()) S.push({1, 1});
            if (h[i] != S.top().Val) S.push({i, h[i]});

            /*计算答案*/
            for (int j = 1; j <= S.tp; j++) {
                int NowAns = (Sum[i] - Sum[S.Stack[j].Pos - 1]) * S.Stack[j].Val;
                if (i - S.Stack[j].Pos + 1 < k) continue;
                Ans = std::max(Ans, NowAns);
            }
        }

        printf("%lld", Ans);
    }
} S_3;

class Subtask_12
{
private:

public:
    void solve()
    {
        int Ans = 0;
        for (int i = 1; i <= n; i++) {
            int Sum = 0, Gcd  = h[i];
            for (int j = i; j >= 1; j--) {
                Sum += h[j];
                Gcd = std::__gcd(Gcd, h[j]);

                if (i - j + 1 >= k) Ans = std::max(Ans, Sum * Gcd);
            }
        }

        printf("%lld", Ans);
    }
} S_12;

signed main()
{
#ifdef FILE_IO
    freopen("intelligence.in", "r", stdin);
    freopen("intelligence.out", "w", stdout);
#endif
    scanf("%lld %lld", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &h[i]), Sum[i] = Sum[i - 1] + h[i];
    
    if (n > 10000) S_3.solve();
    else S_12.solve();

    return 0;
}

只能赶紧冲 T3 , 优化思路能骗 10pts 就非常好了

T3#

没打完, 寄

posted @   Yorg  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示