ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021年度训练联盟热身训练赛第三场(IH)

2021-03-22 20:29:48  阅读:218  来源: 互联网

标签:const int ll tot IH edge 训练赛 第三场 dis


I. Slow Leak(最短路)

传送门

题意:你有一辆轮胎会跑气的自行车,打满一次气可以走的距离是d,一开始自行车的气是满的,城市中有 n 个点,你要从1点到 n 点,其中有 t 个点处可以给自行车打气,你只能在自行车有气的时候走,问从1到 n 的最短路

思路:先跑一遍floyd求出每两点之间的最短路,然后重新构图,两个打气点之间的最短路 <= d时说明可以到达,否则不可以,然后再floyd || dijkstra求1到 n 的最短路。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 507;
const int M = 3e5 + 7;
bool vis[N];
int n, m, t, tot, head[N], ok[N];
ll d, mp[N][N], dis[N];
struct node {
    int u, v, nxt;
    ll w;
} edge[M];

struct A {
    int pos;
    ll cost;
    bool operator < (const A &a) const {
        return cost > a.cost;
    }
};

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
}

void addedge(int u, int v, ll w) {
    edge[tot].u = u;
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nxt = head[u];
    head[u] = tot++;
}

void floyd() {
    for(int k = 1; k <= n; ++k) {
        for(int i = 1; i <= n; ++i) {
            mp[i][i] = 0;
            for(int j = 1; j < i; ++j)
                mp[i][j] = mp[j][i] = min(mp[i][j], mp[i][k] + mp[k][j]);
        }
    }
}

void dijkstra(int src) {
    memset(dis, inf, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[src] = 0;
    priority_queue<A>q;
    q.push(A{src, 0});
    while(!q.empty()) {
        A now = q.top();
        q.pop();
        if(vis[now.pos]) continue;
        vis[now.pos] = 1;
        for(int i = head[now.pos]; ~i; i = edge[i].nxt) {
            int u = edge[i].u, v = edge[i].v;
            if(!vis[v] && dis[v] > dis[u] + edge[i].w) {
                dis[v] = dis[u] + edge[i].w;
                q.push(A{v, dis[v]});
            }
        }
    }
}

int main() {
    int u, v;
    ll w;
    scanf("%d%d%d%lld", &n, &m, &t, &d);
    memset(mp, inf, sizeof(mp));
    for(int i = 1; i <= t; ++i) scanf("%d", &ok[i]);
    ok[t + 1] = 1, ok[t + 2] = n;
    while(m--) {
        scanf("%d%d%lld", &u, &v, &w);
        if(mp[u][v] > w) mp[u][v] = mp[v][u] = w;
    }
    floyd();
    init();
    for(int i = 1; i <= t + 2; ++i) {
        for(int j = i + 1; j <= t + 2; ++j) {
            int u = ok[i], v = ok[j];
            if(mp[u][v] <= d) addedge(u, v, mp[u][v]), addedge(v, u, mp[u][v]);
        }
    }
    dijkstra(1);
    if(dis[n] == inf) printf("stuck\n");
    else printf("%lld\n", dis[n]);
    return 0;
}

J. Stop Counting!(思维)

传送门

题意:一个长度为 n 的数组,选择某个前缀某个后缀某个前缀 + 某个后缀(不重合),问最大平均值

分析:

\frac{a}{b}\leq \frac{a + c}{b + d}\leq\frac{c}{d}

所以要么选前缀,要么选后缀,不会出现某前后缀同时选,取前缀平均值和后缀平均值的最大值即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 1e6 + 7;
const int M = 2e6 + 7;

ll a[N], pre[N], las[N];

int main() {
    int n;
    double max1 = 0, max2 = 0;
    scanf("%d", &n);
    pre[0] = las[n + 1] = 0;
    for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    for(int i = 1; i <= n; ++i) {
        pre[i] = pre[i - 1] + a[i];
        max1 = max(max1, 1.0 * pre[i] / i);
    }
    for(int i = n; i >= 1; --i) {
        las[i] = las[i + 1] + a[i];
        max2 = max(max2, 1.0 * las[i] / (n - i + 1));
    }
    printf("%.10f\n", max(max1, max2));
    return 0;
}

 

标签:const,int,ll,tot,IH,edge,训练赛,第三场,dis
来源: https://blog.csdn.net/weixin_43871207/article/details/115095434

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有