C/C++教程

2021ICPC网络赛第一场【A Busiest Computing Nodes】

本文主要是介绍2021ICPC网络赛第一场【A Busiest Computing Nodes】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

A Busiest Computing Nodes

分析:
很明显的线段树维护区间最小值,之后二分查找。
大的方向没问题,主要是很多小的地方妹处理不好.
1.取模找,类似于形成一个环,这种问题的处理方法其实以前也用过,但是当时忘了,办法是把区间长度搞成两倍即可,明显可以看到代码中线段树开的是1e6 * 4 * 2的
2.二分那部分当时也好混乱,但其实很简单
3.二分结束后,l就是答案,这时需要判断l与k的关系,因为为了方便环我们搞成了2 * k,然后就是更新的时候l与l + k都需要更新。
AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const ll inf = 0x3f3f3f3f3f3f;
ll ar[100050], br[100050];
struct node
{
    ll l, r;
    ll x;
} tree[800050];
ll n, k;
int cnt[100050];
bool flag;

void pushup(ll p)
{
    tree[p].x = min(tree[p<<1].x, tree[p<<1|1].x);
}

void build(ll p, ll l, ll r)
{
    tree[p].l = l;
    tree[p].r = r;

    if(l == r)
    {
        if(l <= k) tree[p].x = ar[l] + br[l];
        else tree[p].x = ar[l - k] + br[l - k];
        return ;
    }

    ll mid = (l + r) >> 1;
    build(p<<1, l, mid);
    build(p<<1|1, mid + 1, r);
    pushup(p);
}

void updata(ll p, ll id, ll x)
{
    if(tree[p].l == tree[p].r && tree[p].l == id)
    {
        tree[p].x = x;
        return ;
    }

    ll mid = (tree[p].l + tree[p].r) >> 1;
    if(mid >= id) updata(p<<1, id, x);
    else updata(p<<1|1, id, x);
    pushup(p);
}

ll query(ll p, ll l, ll r)
{
    if(l <= tree[p].l && tree[p].r <= r)
    {
        return tree[p].x;
    }

    ll mid = (tree[p].l + tree[p].r) >> 1;

    if(r <= mid) return query(p<<1, l, r);
    if(l > mid) return query(p<<1|1, l, r);

    return min(query(p<<1, l, r), query(p<<1|1, l, r));
}

int main()
{
    //cout << inf << '\n';
    scanf("%lld%lld", &k, &n);
    for(int i = 1; i <= n; ++i) scanf("%lld%lld", &ar[i], &br[i]);
    build(1, 1, 2 * k);
    for(int i = 1; i <= k; ++i) ++cnt[i];
    for(int i = k + 1; i <= n; ++i)
    {
        flag = false;
        ll l = i % k;
        if(l == 0) l = k;
        ll r = l + k - 1;
        if(query(1, l, r) > ar[i]) continue;

        while(l < r)
        {
            ll mid = (l + r) >> 1;
            if(query(1, l, mid) <= ar[i]) r = mid;
            else l = mid + 1;
        }
        if(l > k) l -= k;
        ++cnt[l];
        updata(1, l, ar[i] + br[i]);
        updata(1, l + k, ar[i] + br[i]);
    }
    int mx = 0, ans;
    for(int i = 1; i <= k; ++i)
    {
        mx = max(mx, cnt[i]);
    }
    flag = false;
    for(int i = 1; i <= k; ++i)
    {
        if(mx == cnt[i])
        {
            if(flag)
            {
                printf(" %d", i - 1);
            }
            else
            {
                printf("%d", i - 1);
                flag = true;
            }
        }
    }
    //printf("%d", ans - 1);
    return 0;
}

另外,学习了一下dalao的代码,代码量很少,毕竟因为线段树维护的东西比较简单,没有直接定义结构体,也没有写build(1,1,n)这个函数。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll maxn = 1e6 + 5;
ll t[maxn<<3], cnt[maxn];
ll n, k;
ll a, b;

ll query(ll p, ll l, ll r, ll x, ll y)
{
    if(x <= l && r <= y) return t[p];

    ll mid = (l + r) >> 1;
    if(y <= mid) return query(p<<1, l, mid, x, y);
    if(x > mid) return query(p<<1|1, mid + 1, r, x, y);
    return min(query(p<<1, l, mid, x, y), query(p<<1|1, mid + 1, r, x, y));
}

void updata(ll p, ll l, ll r, ll id, ll x)
{
    if(l == r) return void(t[p] = x);

    ll mid = (l + r) >> 1;
    if(id <= mid) updata(p<<1, l, mid, id, x);
    if(id > mid) updata(p<<1|1, mid + 1, r, id, x);

    t[p] = min(t[p<<1], t[p<<1|1]);
}

int main()
{
    scanf("%lld%lld", &k, &n);
    ll mx = 0;
    for(int i = 1; i <= n; ++i)
    {
        scanf("%lld%lld", &a, &b);
        ll l = i % k;
        if(l == 0) l = k;
        ll r = l + k - 1;
        if(query(1, 1, 2 * k, l, r) > a) continue;

        while(l < r)
        {
            ll mid = (l + r) >> 1;
            if(query(1, 1, 2 * k, l, mid) <= a) r = mid;
            else l = mid + 1;
        }

        if(l > k) l -= k;
        ++cnt[l];
        mx = max(mx, cnt[l]);
        updata(1, 1, 2 * k, l, a + b);
        updata(1, 1, 2 * k, l + k, a + b);
    }
    bool flag = false;
    for(int i = 1; i <= k; ++i)
    {
        if(cnt[i] == mx)
        {
            if(flag) printf(" %d", i - 1);
            else
            {
                printf("%d", i - 1);
                flag = true;
            }
        }
    }
    return 0;
}

这篇关于2021ICPC网络赛第一场【A Busiest Computing Nodes】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!