ICode9

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

2020.9.19 ICPC网络选拔赛 第一场

2021-09-20 11:34:44  阅读:305  来源: 互联网

标签:2020.9 19 cin ICPC int map1 2021 printf id


A Busiest Computing Nodes

在这里插入图片描述

题意

有 k k k台机器和 n n n条指令。对于一条指令(编号为 i i i)来说,如果它到的时候,所有的机器都在完成其他的指令,那么这条指令作废;否则,从第 i i%k i个机器开始从前往后扫描,遇到第一个空闲的机器执行这条指令。请求出执行指令最多的机器,如果有多个,按照序号升序输出。

思路

首先,我们要判断指令到达的时候是否全部机器都在执行指令,那么我们就需要记录所有机器最早什么时候才能完成工作(即最早的指令完成时间),可以用 s e t + m a p set+map set+map进行记录, s e t set set可以自动排序,随时可以找到最早的时间, m a p map map记录每个时间的个数,因为可以有多台机器在同一时间完成指令。当 m a p map map所对应的时间的个数为0时,需要在set里把该时间删掉。
然后,就是如何快速找到第一个空闲的机器,如果直接线性搜索的话,很有可能TLE,那么我们可以通过线段树去存储每个机器的结束时间和区间的最小值,(注意:线段树从1开始,而机器从0开始,需要+1匹配),并且开一个 2 ∗ k 2*k 2∗k的线段树,找的时候直接找 [ i % k + 1 , i % k + k ] [i\%k+1,i\%k+k] [i%k+1,i%k+k]区间(已经+1)即可,然后通过二分找到第一个空闲的机器。

代码

/*
 * @Author: Icey_dying
 * @Date: 2021-09-20 10:28:45
 * @LastEditors: Icey_dying
 * @LastEditTime: 2021-09-20 10:49:00
 * @FilePath: \Icey_dying\competition\2021\2021.09\2021.9.19\A.cpp
 */
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N << 2], tr[N << 3], cnt[N];
set<int> s;
map<int, int> m;

void bulid(int i, int l, int r)
{
    if (l == r) {
        tr[i] = 0x3f3f3f3f;
        return;
    }
    int mid = l + r >> 1;
    bulid(i << 1, l, mid);
    bulid(i << 1 | 1, mid + 1, r);
    tr[i] = min(tr[i << 1], tr[i << 1 | 1]);
}

void update(int i, int l, int r, int x, int y)
{
    if (l > x || x > r)
        return;
    if (l == r && l == x) {
        tr[i] = y;
        return;
    }
    int mid = l + r >> 1;
    update(i << 1, l, mid, x, y);
    update(i << 1 | 1, mid + 1, r, x, y);
    tr[i] = min(tr[i << 1], tr[i << 1 | 1]);
}

int query(int i, int l, int r, int x, int y)
{
    if (y < l || x > r)
        return 0x3f3f3f3f;
    if (l >= x && r <= y)
        return tr[i];
    int mid = l + r >> 1;
    return min(query(i << 1, l, mid, x, y), query(i << 1 | 1, mid + 1, r, x, y));
}

int f(int l, int r, int x, int k)
{
    if (l == r)
        return l;
    int mid = (l + r) / 2;
    if (query(1, 1, 2 * k, l, mid) < x)//为了查到第一个,需要先查左边
        f(l, mid, x, k);
    else
        f(mid + 1, r, x, k);
}

int main()
{
    int k, n;
    cin >> k >> n;
    bulid(1, 1, 2 * k);
    s.insert(0);
    m[0] = k;
    for (int i = 0; i < n; ++i) {
        int l, time;
        cin >> l >> time;
        if (*s.begin() >= l)
            continue;
        if (a[i % k] < l) {
            cnt[i % k]++;
            m[a[i % k]]--;
            if (m[a[i % k]] == 0)
                s.erase(a[i % k]);
            a[i % k] = l + time - 1;
            if (s.find(a[i % k]) == s.end())
                s.insert(a[i % k]);
            m[a[i % k]]++;
            //同时更新i%k和i%k+k
            update(1, 1, 2 * k, (i % k) + 1, l + time - 1);//在线段树上+1
            update(1, 1, 2 * k, (i % k) + k + 1, l + time - 1);//在线段树上+1
        } else {
            int id = f(i % k + 1, i % k + k, l, k);
            id--;
            id %= k;
            cnt[id]++;
            m[a[id]]--;
            if (m[a[id]] == 0)
                s.erase(a[id]);
            a[id] = l + time - 1;
            if (s.find(a[id]) == s.end())
                s.insert(a[id]);
            m[a[id]]++;
            update(1, 1, 2 * k, id + 1, l + time - 1);
            update(1, 1, 2 * k, id + k + 1, l + time - 1);
        }
    }
    int minx = 0, ans = 0;
    for (int i = 0; i < k; i++)
        minx = max(minx, cnt[i]);
    for (int i = 0; i < k; i++) {
        if (cnt[i] == minx) {
            if (ans)
                printf(" ");
            printf("%d", i);
            ans++;
        }
    }
    return 0;
}

ps.队友打线段树板子的时候疏忽了,query那里有个&&打成了||,导致我们晚了快一个小时才AC,太难了~~

F Land Overseer

在这里插入图片描述

题意

平面直角坐标系中有三个点, O ( 0 , 0 ) , A ( a , b ) , B ( 2 × a , 0 ) O(0,0),A(a,b),B(2\times a,0) O(0,0),A(a,b),B(2×a,0),现在需要从 O O O点出发,经过以 A A A和 B B B为圆心, r r r为半径的圆。求最短路径。

思路

如果圆足够大,使得圆能覆盖的 x x x轴,则直接走向 B B B,距离为 2 × a − r 2\times a-r 2×a−r
如果不够大,则先走到以 A A A为圆心的圆的最低点,然后再径直走向 B B B,距离为 ( a − 0 ) 2 + ( b − r ) 2 + ( 2 × a − a ) 2 + ( 0 − ( b − r ) ) 2 − r = 2 × a 2 + ( b − r ) 2 − r \sqrt{(a-0)^{2}+(b-r)^{2}}+\sqrt{(2\times a-a)^{2}+(0-(b-r))^{2}-r}=2\times \sqrt{a^{2}+(b-r)^{2}}-r (a−0)2+(b−r)2 ​+(2×a−a)2+(0−(b−r))2−r ​=2×a2+(b−r)2 ​−r

/*
 * @Author: Icey_dying
 * @Date: 2021-09-20 10:29:01
 * @LastEditors: Icey_dying
 * @LastEditTime: 2021-09-20 11:06:50
 * @FilePath: \Icey_dying\competition\2021\2021.09\2021.9.19\F.cpp
 */
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N];

int main()
{
    int t;
    cin >> t;
    for (int i = 1; i <= t; ++i) {
        double a, b, r;
        cin >> a >> b >> r;
        if (r >= b) {
            printf("Case #%d: %.2f\n", i, 2 * a - r);
        } else {
            printf("Case #%d: %.2f\n", i, 2 * sqrt(a * a + (b - r) * (b - r)) - r);
        }
    }
    return 0;
}

H Mesh Analysis

在这里插入图片描述
在这里插入图片描述

题意

三维空间有一些点,并且还有三角网和线段,对于属于同一个三角网和同一条线段的点,互为相邻点,求每个点的相邻点和属于哪个三角网或线段。

思路

这题应该算是比较简单的题了,仅次于F。直接用set存相邻点和所属标号即可,注意输入的都是id,要用map存一下每个编号对应的是第几个点。

代码

/*
 * @Author: Icey_dying
 * @Date: 2021-09-20 10:29:24
 * @LastEditors: Icey_dying
 * @LastEditTime: 2021-09-20 10:29:25
 * @FilePath: \Icey_dying\competition\2021\2021.09\2021.9.19\H.cpp
 */
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m;
set<int> s1[N], s2[N];
map<int, int> map1;
void insert111(int a, int b)
{
    if (s1[map1[a]].find(b) == s1[map1[a]].end())
        s1[map1[a]].insert(b);
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    int id, biao, a, b, c;
    double x, y, z;
    for (int i = 1; i <= n; i++) {
        cin >> id;
        map1[id] = i;
        cin >> x >> y >> z;
        // printf("%lf %lf %lf\n", x, y, z);
    }
    for (int i = 1; i <= m; i++) {
        cin >> id >> biao;
        switch (biao) {
        case 102:
            cin >> a >> b;
            insert111(a, b); insert111(b, a);
            s2[map1[a]].insert(id);
            s2[map1[b]].insert(id);
            break;
        case 203:
            cin >> a >> b >> c;
            insert111(a, b); insert111(a, c);
            insert111(b, c); insert111(b, a);
            insert111(c, a); insert111(c, b);
            s2[map1[a]].insert(id);
            s2[map1[b]].insert(id);
            s2[map1[c]].insert(id);
        }
    }
    int t;
    cin >> t;
    while (t--) {
        cin >> id;
        if (map1[id] == 0) {
            printf("%d\n[]\n[]\n", id);
        } else {
            printf("%d\n[", id);
            for (auto i : s1[map1[id]]) {
                if (i != *s1[map1[id]].begin())
                    printf(",");
                printf("%d", i);
            }
            printf("]\n[");
            for (auto i : s2[map1[id]]) {
                if (i != *s2[map1[id]].begin())
                    printf(",");
                printf("%d", i);
            }
            printf("]\n");
        }
    }
    return 0;
}

I Neighborhood Search

在这里插入图片描述

题意

给出S里面的点,给出A的值和r,求出S中点的值与A的差值小于等于r的点,降序输出

思路

直接找就行,输入对于C++有些麻烦,队友直接用Python写出来了

代码

lst = list(map(int, input().split()))
x = int(input())
r = int(input())
lst.sort()
flag = 0
for i in range(len(lst) - 1, -1, -1):
    if abs(lst[i] - x) <= r:
        print(lst[i], end=" ")
        flag = 1
if flag == 0:
    print()

K Segment Routing

在这里插入图片描述

题意

给出一些点和它们的边(有编号),再给出一些路径,看是否能到达另外的点,如果可以,输出该点的编号,否则输出"Packet Loss"

思路

用vector记录边即可,注意判断"Packet Loss"的时候,不要直接break,那样会让数据输入产生混乱,我们就是因为这个没有AC

代码

/*
 * @Author: Icey_dying
 * @Date: 2021-09-20 10:30:11
 * @LastEditors: Icey_dying
 * @LastEditTime: 2021-09-20 11:22:06
 * @FilePath: \Icey_dying\competition\2021\2021.09\2021.9.19\K.cpp
 */
#include <bits/stdc++.h>
using namespace std;
int n, m;
const int N = 1e5 + 50;
vector<int> v[N];

int main()
{
    int t;
    scanf("%d", &t);
    for (int k = 1; k <= t; k++) {
        scanf("%d%d", &n, &m);
        int xx, u;
        for (int i = 1; i <= n; i++) {
            v[i].clear();
            cin >> xx;
            for (int j = 1; j <= xx; j++) {
                scanf("%d", &u);
                v[i].push_back(u);
            }
        }
        printf("Case #%d: \n", k);
        for (int j = 1; j <= m; j++) {
            bool flag = 0;
            scanf("%d %d", &u, &k);
            int vv = u, id;
            for (int i = 1; i <= k; i++) {
                scanf("%d", &id);
                if (id > v[vv].size() || id == 0)
                    flag = 1;
                if (flag == 1)
                    continue;

                vv = v[vv][id - 1];
            }
            if (flag)
                printf("Packet Loss\n");
            else {
                printf("%d\n", vv);
            }
        }
    }
    return 0;
}

标签:2020.9,19,cin,ICPC,int,map1,2021,printf,id
来源: https://blog.csdn.net/Icey_dying/article/details/120388680

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

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

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

ICode9版权所有