河南萌新联赛2024第(五)场:信息工程大学

碎碎念:这场有点水,原和板子太多了,写着写着就跑去睡觉了QWQ

目录

A-日历游戏

B-学生分组

C-关押罪犯

D-区间问题1

E-哥德巴赫猜想

F-小美想跑步

G-爬楼梯

H-区间问题2

I-小美想打音游

J-平方根

K-小美想游泳


A-日历游戏

思路:找规律,可发现大部分情况下日期+月数为奇数时先手必胜,有两个特殊日期9.30和11.30,加日就能避免操作后奇偶性变化保证必胜。

void solve()
{
    int x,y,z;
    std::cin>>x>>y>>z;
    if((y==9&&z==30)||(y==11&&z==30)||(y+z)%2==0) std::cout<<"YES\n";
    else std::cout<<"NO\n";
}

B-学生分组

思路:总人数<组数*L和总人数>组数*R(即判断平均数是否在区间里)输出-1

        然后就是多出的人数去补缺少的人数,取max即可

        注意开longlong,代码#define int long long 了

void solve()
{
    int n;
    std::cin>>n;

    std::vector<int>a(n,0);
    i64 res=0;

    for(auto &x:a) std::cin>>x,res+=x;
    int l,r;
    std::cin>>l>>r;
    if(res<n*l||res>n*r)
    {
        std::cout<<"-1\n";
        return;
    }

    int b=0,c=0;
    for(int i=0;i<n;i++)
    {
        if(a[i]<l) b+=l-a[i];
        else if(a[i]>r) c+=a[i]-r;
    }

    std::cout<<std::max(b,c)<<'\n';

}

C-关押罪犯

换上原题面

思路:种类(扩展域)并查集板子题,贪心的从大到小排序冲突值,优先处理冲突值高的,维护两个集合,若x与y冲突,则合并(x,y+n)和(x+n,y),直至枚举到的x,y在已经在一个集合中了就可以确定冲突值了,注意没冲突时冲突值为0

void solve()
{
    int n,m;
    std::cin>>n>>m;
    std::vector<std::tuple<i64 ,int ,int >>g;
    for(int i=0;i<m;i++)
    {
        i64 u,v,w;
        std::cin>>u>>v>>w;
        g.pb({w,u,v});
    }

    std::sort(g.begin(), g.end(),std::greater<>());


    DSU dsu(2*n);

    i64 res=0;
    for(int i=0;i<m;i++)
    {
        auto [w,u,v]=g[i];
        if(dsu.find(u)==dsu.find(v)||dsu.find(u+n)==dsu.find(v+n))
        {
            res=w;
            break;
        }
        dsu.merge(u+n,v);
        dsu.merge(v+n,u);
    }

    std::cout<<res<<'\n';

}

D-区间问题1

思路:本来想上线段树的,但看到过题数似乎有点多了就猜数据可能水了,交一发暴力还真过了

void solve()
{
    int n;
    std::cin>>n;
    std::vector<int>a(n,0);
    for(auto &x:a) std::cin>>x;
    int q;
    std::cin>>q;
    while (q--)
    {
        int op;
        std::cin>>op;
        if(op==1)
        {
            int l,r,c;
            std::cin>>l>>r>>c;
            l--,r--;
            for(int i=l;i<=r;i++) a[i]+=c;
        }
        else
        {
            int x;
            std::cin>>x;
            x--;
            std::cout<<a[x]<<'\n';
        }
    }
}

E-哥德巴赫猜想

思路:暴力搞了一下,赛后看别人代码发现可以先筛出5e4的质数,然后set维护第三个数

void solve()
{
    auto check=[&](i64 x)->bool
    {
        for(int i=2;i<=x/i;i++)
            if(x%i==0) return false;
        return true;
    };

    i64 x;
    std::cin>>x;

    if(check(x-4))
    {
        std::cout<<"2 2 "<<x-4<<'\n';
        return;
    }

    for(int i=3;i<x;i++)
    {
        if((i%2)!=0&&check(i))
            for (int j=i;j<x;j++)
                if((j%2)!=0&&check(j))
                    if(check(x-i-j))
                    {
                        std::cout<<i<<" "<<j<<" "<<x-i-j<<'\n';
                        return;
                    }
                       
    }

}

F-小美想跑步

思路:有向图中起点到到其他点的最短距离,和其他点到起点的最短距离

void solve()
{
    int n, m;
    std::cin >> n >> m;

    DIJ dij1(n), dij2(n);
    for (int i = 0; i < m; i ++) 
    {
        int u, v, w;
        std::cin >> u >> v >> w;
        dij1.add(u, v, w);
        dij2.add(v, u, w);
    }

    dij1.dijkstra(1);
    dij2.dijkstra(1);

    i64 ans = 0;
    for (int i = 2; i <= n; i ++)
        ans += dij1.dis[i] + dij2.dis[i];

    std::cout << ans << '\n';
    
}

G-爬楼梯

思路:简单dp f[i]=f[i-1]+f[i-2]+f[i-3]

void solve()
{
    int n;
    std::cin>>n;
    std::vector<int>f(n+1,0);
    f[0]=1,f[1]=2,f[2]=4;
    for(int i=3;i<n;i++) f[i]=((f[i-1]+f[i-2])%mod+f[i-3])%mod;
    
    std::cout<<f[n-1]<<'\n';

}

H-区间问题2

思路:ST表

void solve()
{
    int n;
    std::cin>>n;
    std::vector<std::vector<int>>f(n+1,std::vector<int>(20,0));
    for(int i=1;i<=n;i++) std::cin>>f[i][0];

    for(int j=1;j<=20;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            f[i][j]=std::max(f[i][j-1],f[i+(1<<(j-1))][j-1]);

    int q;
    std::cin>>q;
    while (q--)
    {
        int l,r;
        std::cin>>l>>r;
        int k=log2(r-l+1);
        std::cout<<std::max(f[l][k],f[r-(1<<k)+1][k])<<'\n';
    }

}

I-小美想打音游

思路:中位数贪心

void solve()
{
    int n;
    std::cin>>n;
    std::vector<int>a(n,0);
    for(auto &x:a) std::cin>>x;
    std::sort(a.begin(), a.end());
    if(n&1)
    {
        int x=n/2;
        i64 res=0;
        std::cerr<<a[x]<<'\n';
        for(int i=0;i<n;i++) res+=std::abs(a[i]-a[x]);
        std::cout<<res+1<<'\n';
    }
    else
    {
        i64 res=0;
        int x=n/2;
        int mid=(a[x]+a[x-1])/2;
        std::cerr<<a[x]<<' '<<a[x-1]<<'\n';
        std::cerr<<a[mid]<<'\n';
        for(int i=0;i<n;i++) res+=std::abs(a[i]-mid);
        std::cout<<res+1<<'\n';
    }

}

J-平方根

思路:签到题

void solve()
{
    i64 n;
    std::cin>>n;
    std::cout<<(i64)__builtin_sqrt(n)<<'\n';
}

K-小美想游泳

思路:堆优化的dij维护路径的最大值

void solve()
{
    int n,m;
    std::cin>>n>>m;
    DIJ dij(n);
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        std::cin>>u>>v>>w;
        dij.add(u,v,w);
        dij.add(v,u,w);
    }

    int s,t;
    std::cin>>s>>t;

    dij.dijkstra(s);

    std::cout<<dij.dis[t]<<'\n';

}

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值