ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-09-22 20:02:25  阅读:259  来源: 互联网

标签:return Computing Busiest tree mid 2021ICPC mx flag ll


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;
}

标签:return,Computing,Busiest,tree,mid,2021ICPC,mx,flag,ll
来源: https://blog.csdn.net/qq_33969563/article/details/120421710

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

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

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

ICode9版权所有