ICode9

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

Codeforces Round #611 (Div. 3)

2020-01-21 13:55:13  阅读:316  来源: 互联网

标签:return 200005 mlen int 611 Codeforces ans Div check


A - Minutes Before the New Year

题意:问现在的时间距离0点0分有多少分钟,提问的时间在0点0分之前,且不是0点0分。

题解:?

void test_case() {
    int h, m;
    scanf("%d%d", &h, &m);
    int ans = 0;
    if(m == 0)
        ans += (24 - h) * 60;
    else {
        ans += (23 - h) * 60;
        ans += 60 - m;
    }
    printf("%d\n", ans);
}

B - Candies Division

题意:把n颗糖分给k个人,可以留下一些糖,要求分配的最大值与最小值的差不超过1(尽可能平均),且比最小值多1的人数量不超过一半,在此基础上尽可能多分配。

题解:先平均分配下整,然后零头加上去。

void test_case() {
    int n, k;
    scanf("%d%d", &n, &k);
    int a = n / k;
    int ans = k * a;
    int surplus = min(k / 2, n - ans);
    ans += surplus;
    printf("%d\n", ans);
}

C - Friends and Gifts

题意:每个人必须恰好给出1颗糖果,恰好得到1颗糖果,p[i]表示他要给谁,0表示他等待分配,输入保证不矛盾。分配每个人要给谁,使得满足题目约束。

题解:这张图就是若干条链和若干个环,环不影响直接去掉,然后链全部首尾相连。

int s[200005];
int p[200005];
int h[200005];
int t[200005];
int cnt;
 
int dfs(int u) {
    if(s[u] != 0)
        return dfs(s[u]);
    else
        return u;
}
 
void test_case() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &p[i]);
        s[p[i]] = i;
    }
    cnt = 0;
    for(int i = 1; i <= n; ++i) {
        if(p[i] == 0) {
            if(s[i] == 0) {
                ++cnt;
                h[cnt] = i;
                t[cnt] = i;
            } else {
                ++cnt;
                h[cnt] = i;
                t[cnt] = dfs(i);
            }
            //printf("h=%d\n",h[cnt]);
            //printf("t=%d\n",t[cnt]);
        }
    }
    int j = 1;
    for(int i = 1; i <= n; ++i) {
        if(p[i] == 0) {
            p[i] = t[++j];
            if(j > cnt)
                p[i] = t[1];
        }
    }
    for(int i = 1; i <= n; ++i)
        printf("%d%c", p[i], " \n"[i == n]);
}

D - Christmas Trees

题意:数轴上有n棵圣诞树,位置分别是xi。给m个人分配位置,使得所有人到离他最近的圣诞树的距离的和最小。

题解:直接贪心往每棵树两边加人即可。用了一个丑陋的实现,先二分确定可以加的值,然后再加。

int n, m;
int x[200005];
 
bool check(int mlen) {
    ll sumpoints = 2 * mlen;
    for(int i = 2; i <= n; ++i) {
        sumpoints += min(x[i] - x[i - 1] - 1, 2 * mlen);
        if(sumpoints >= m) {
            //printf("check mlen=%d, suc.\n", mlen);
            return true;
        }
    }
    if(sumpoints >= m) {
        //printf("check mlen=%d, suc.\n", mlen);
        return true;
    }
    //printf("check mlen=%d, fail.\n", mlen);
    return false;
}
 
int ans[200005];
 
priority_queue<pii> pq;
 
ll answer(int mlen) {
    for(int j = 1; j <= mlen; ++j)
        pq.push({-j, x[1] - j});
    for(int j = 1; j <= mlen; ++j)
        pq.push({-j, x[n] + j});
    for(int i = 1; i < n; ++i) {
        if(x[i + 1] - x[i] - 1 > 2 * mlen) {
            for(int j = 1; j <= mlen; ++j)
                pq.push({-j, x[i] + j});
            for(int j = 1; j <= mlen; ++j)
                pq.push({-j, x[i + 1] - j});
        } else {
            int dis = (x[i + 1] - x[i]);
            for(int j = 1; ; ++j) {
                if(x[i] + j == x[i + 1])
                    break;
                pq.push({-(min(j, dis - j)), x[i] + j});
            }
        }
    }
 
    ll res = 0;
    for(int j = 1; j <= m; ++j) {
        ans[j] = pq.top().second;
        res += (-pq.top().first);
        //cout << "x=" << pq.top().second << endl;
        //cout << "d=" << (-pq.top().first) << endl;
        pq.pop();
    }
    while(pq.size())
        pq.pop();
    return res;
}
 
ll bs() {
    int l = 1, r = m;
    while(1) {
        int mid = l + r >> 1;
        if(l == mid) {
            if(check(l))
                return answer(l);
            assert(check(r));
            return answer(r);
        }
        if(check(mid))
            r = mid;
        else
            l = mid + 1;
    }
}
 
 
void test_case() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &x[i]);
    if(n == 1) {
        ll sum = 0;
        int l = x[1], r = x[1];
        for(int i = 1; i <= m; ++i) {
            if(i & 1) {
                ans[i] = --l;
                sum += x[1] - l;
            } else {
                ans[i] = ++r;
                sum += r - x[1];
            }
        }
        printf("%lld\n", sum);
        sort(ans + 1, ans + 1 + m);
        for(int i = 1; i <= m; ++i)
            printf("%d%c", ans[i], " \n"[i == m]);
        return;
    }
    sort(x + 1, x + 1 + n);
    printf("%lld\n", bs());
    sort(ans + 1, ans + 1 + m);
    for(int i = 1; i <= m; ++i)
        printf("%d%c", ans[i], " \n"[i == m]);
}

但是其实可以存每棵树的l指针和r指针,当某棵树的r指针遇到另一棵树的l指针的时候就把这两个指针去掉。不过这样写起来不见得比二分好写。先二分的原因是可以避免把过多的点插进优先队列。

E - New Year Parties

题意:有n个人,每个人可以左移1、右移1或者留在原地。求最小覆盖多少个点和最大覆盖多少个点。

题解:很明显满足dp的性质。只是很容易漏掉一些转移。

int n;
int x[200005];
int dp[200005][8];
 
void test_case() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &x[i]);
        ++x[i];
    }
    sort(x + 1, x + 1 + n);
    //xi value range [2,n+1]
    //can move to value range [1,n+2]
 
    //MIN
    memset(dp, INF, sizeof(dp));
    dp[0][0] = 0;
    for(int i = 1; i <= n; ++i) {
        if(i == 1 || x[i] == x[i - 1]) {
            //move to left
            dp[i][4] = min(dp[i - 1][4], dp[i - 1][0] + 1);
            dp[i][5] = min(dp[i - 1][5], dp[i - 1][1] + 1);
            dp[i][6] = min(dp[i - 1][6], dp[i - 1][2] + 1);
            dp[i][7] = min(dp[i - 1][7], dp[i - 1][3] + 1);
            //stay here
            dp[i][2] = min(dp[i - 1][2], dp[i - 1][0] + 1);
            dp[i][3] = min(dp[i - 1][3], dp[i - 1][1] + 1);
            dp[i][6] = min(dp[i][6], min(dp[i - 1][6], dp[i - 1][4] + 1));
            dp[i][7] = min(dp[i][7], min(dp[i - 1][7], dp[i - 1][5] + 1));
            //move to right
            dp[i][1] = min(dp[i - 1][1], dp[i - 1][0] + 1);
            dp[i][3] = min(dp[i][3], min(dp[i - 1][3], dp[i - 1][2] + 1));
            dp[i][5] = min(dp[i][5], min(dp[i - 1][5], dp[i - 1][4] + 1));
            dp[i][7] = min(dp[i][7], min(dp[i - 1][7], dp[i - 1][6] + 1));
        } else {
            if(x[i] == x[i - 1] + 1) {
                //move to left
                dp[i][4] = min(min(dp[i - 1][2], dp[i - 1][6]), min(dp[i - 1][0], dp[i - 1][4]) + 1);
                dp[i][6] = min(min(dp[i - 1][3], dp[i - 1][7]), min(dp[i - 1][1], dp[i - 1][5]) + 1);
                //stay here
                dp[i][2] = min(min(dp[i - 1][1], dp[i - 1][5]), min(dp[i - 1][0], dp[i - 1][4]) + 1);
                dp[i][6] = min(dp[i][6], min(min(dp[i - 1][3], dp[i - 1][7]), min(dp[i - 1][2], dp[i - 1][6]) + 1));
                //move to right
                dp[i][1] = min(dp[i - 1][0], dp[i - 1][4]) + 1;
                dp[i][3] = min(dp[i - 1][1], dp[i - 1][5]) + 1;
                dp[i][5] = min(dp[i - 1][2], dp[i - 1][6]) + 1;
                dp[i][7] = min(dp[i - 1][3], dp[i - 1][7]) + 1;
            } else if(x[i] == x[i - 1] + 2) {
                //move to left
                dp[i][4] = min(min(dp[i - 1][1], dp[i - 1][3]), min(dp[i - 1][5], dp[i - 1][7]));
                for(int j = 0; j <= 7; j += 2)
                    dp[i][4] = min(dp[i][4], dp[i - 1][j] + 1);
                //stay here
                for(int j = 0; j <= 7; j += 2)
                    dp[i][2] = min(dp[i][2], dp[i - 1][j] + 1);
                for(int j = 1; j <= 7; j += 2)
                    dp[i][6] = min(dp[i][6], dp[i - 1][j] + 1);
                //move to right
                for(int j = 0; j <= 7; j += 2)
                    dp[i][1] = min(dp[i][1], dp[i - 1][j] + 1);
                for(int j = 1; j <= 7; j += 2)
                    dp[i][5] = min(dp[i][5], dp[i - 1][j] + 1);
            } else {
                //move to left
                for(int j = 0; j <= 7; ++j)
                    dp[i][4] = min(dp[i][4], dp[i - 1][j] + 1);
                //stay here
                for(int j = 0; j <= 7; ++j)
                    dp[i][2] = min(dp[i][2], dp[i - 1][j] + 1);
                //move to right
                for(int j = 0; j <= 7; ++j)
                    dp[i][1] = min(dp[i][1], dp[i - 1][j] + 1);
            }
        }
        /*for(int j = 0; j <= 7; ++j)
            printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
        printf("\n");*/
    }
    int ans1 = INF;
    for(int j = 0; j <= 7; ++j)
        ans1 = min(ans1, dp[n][j]);
 
 
    //MAX
    memset(dp, -INF, sizeof(dp));
    dp[0][0] = 0;
    for(int i = 1; i <= n; ++i) {
        if(i == 1 || x[i] == x[i - 1]) {
            //move to left
            dp[i][4] = max(dp[i - 1][4], dp[i - 1][0] + 1);
            dp[i][5] = max(dp[i - 1][5], dp[i - 1][1] + 1);
            dp[i][6] = max(dp[i - 1][6], dp[i - 1][2] + 1);
            dp[i][7] = max(dp[i - 1][7], dp[i - 1][3] + 1);
            //stay here
            dp[i][2] = max(dp[i - 1][2], dp[i - 1][0] + 1);
            dp[i][3] = max(dp[i - 1][3], dp[i - 1][1] + 1);
            dp[i][6] = max(dp[i][6], max(dp[i - 1][6], dp[i - 1][4] + 1));
            dp[i][7] = max(dp[i][7], max(dp[i - 1][7], dp[i - 1][5] + 1));
            //move to right
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + 1);
            dp[i][3] = max(dp[i][3], max(dp[i - 1][3], dp[i - 1][2] + 1));
            dp[i][5] = max(dp[i][5], max(dp[i - 1][5], dp[i - 1][4] + 1));
            dp[i][7] = max(dp[i][7], max(dp[i - 1][7], dp[i - 1][6] + 1));
        } else {
            if(x[i] == x[i - 1] + 1) {
                //move to left
                dp[i][4] = max(max(dp[i - 1][2], dp[i - 1][6]), max(dp[i - 1][0], dp[i - 1][4]) + 1);
                dp[i][6] = max(max(dp[i - 1][3], dp[i - 1][7]), max(dp[i - 1][1], dp[i - 1][5]) + 1);
                //stay here
                dp[i][2] = max(max(dp[i - 1][1], dp[i - 1][5]), max(dp[i - 1][0], dp[i - 1][4]) + 1);
                dp[i][6] = max(dp[i][6], max(max(dp[i - 1][3], dp[i - 1][7]), max(dp[i - 1][2], dp[i - 1][6]) + 1));
                //move to right
                dp[i][1] = max(dp[i - 1][0], dp[i - 1][4]) + 1;
                dp[i][3] = max(dp[i - 1][1], dp[i - 1][5]) + 1;
                dp[i][5] = max(dp[i - 1][2], dp[i - 1][6]) + 1;
                dp[i][7] = max(dp[i - 1][3], dp[i - 1][7]) + 1;
            } else if(x[i] == x[i - 1] + 2) {
                //move to left
                for(int j = 1; j <= 7; j += 2)
                    dp[i][4] = max(dp[i][4], dp[i - 1][j]);
                for(int j = 0; j <= 7; j += 2)
                    dp[i][4] = max(dp[i][4], dp[i - 1][j] + 1);
                //stay here
                for(int j = 0; j <= 7; j += 2)
                    dp[i][2] = max(dp[i][2], dp[i - 1][j] + 1);
                for(int j = 1; j <= 7; j += 2)
                    dp[i][6] = max(dp[i][6], dp[i - 1][j] + 1);
                //move to right
                for(int j = 0; j <= 7; j += 2)
                    dp[i][1] = max(dp[i][1], dp[i - 1][j] + 1);
                for(int j = 1; j <= 7; j += 2)
                    dp[i][5] = max(dp[i][5], dp[i - 1][j] + 1);
            } else {
                //move to left
                for(int j = 0; j <= 7; ++j)
                    dp[i][4] = max(dp[i][4], dp[i - 1][j] + 1);
                //stay here
                for(int j = 0; j <= 7; ++j)
                    dp[i][2] = max(dp[i][2], dp[i - 1][j] + 1);
                //move to right
                for(int j = 0; j <= 7; ++j)
                    dp[i][1] = max(dp[i][1], dp[i - 1][j] + 1);
            }
        }
        /*for(int j = 0; j <= 7; ++j)
            printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
        printf("\n");*/
    }
    int ans2 = 0;
    for(int j = 0; j <= 7; ++j)
        ans2 = max(ans2, dp[n][j]);
 
    printf("%d %d\n", ans1, ans2);
}

好像有贪心的写法?

标签:return,200005,mlen,int,611,Codeforces,ans,Div,check
来源: https://www.cnblogs.com/KisekiPurin2019/p/12221463.html

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

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

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

ICode9版权所有