Codeforces 进阶计划:从 Specialist 到 Expert

训练计划:做 Codeforces Round (Div. 3)、Codeforces Round (Div. 3) 和 Educational Codeforces Round 通过人数少于 1000 人的题目。

目前做了 3 题。

Codeforces Round #490 (Div. 3)

D. Equalize the Remainders

给定两个整数 n , m n 个整数 a 1 , a 2 , . . . , a n 组成的数列 A ,每次可以将数列 A 中的任意一个整数加 1 ,至少需要多少次操作才能使得在所有 A i mod m 中, 0 , 1 , . . . , m 1 都出现 n m 次。
数据保证 m | n 1 m n 2 × 10 5 , 0 a i 10 9

对于每个余数,统计在数列中的下标,将余数数列复制一份到末尾,每次余数个数大于 n m 的部分加入队列,对于小于 n m 的部分尝试用队列中的数补齐即可。

#include <cstdio>
#include <queue>
typedef long long int ll;
const int maxn=(int)2e5+5;
int arr[maxn],add[maxn];
std::queue<int> remainders[2*maxn];
struct element {int id,val;};
int main() {
    int n,m;scanf("%d%d",&n,&m);
    int cnt=n/m;
    for(int i=0;i<n;++i) {
        scanf("%d",&arr[i]);
        remainders[arr[i]%m].push(i);
        remainders[arr[i]%m+m].push(i);
    }
    std::queue<element> q;ll ans=0;
    for(int i=0;i<2*m;++i) {
        while(remainders[i].size()>cnt) {
            q.push((element){remainders[i].front(),i});
            remainders[i].pop();
            if(i<m) remainders[i+m].pop();
            else remainders[i-m].pop();
        }
        while(remainders[i].size()<cnt&&q.size()) {
            element ele=q.front();q.pop();
            ans+=add[ele.id]=i-ele.val;
            remainders[i].push(ele.id);
            if(i<m) remainders[i+m].push(ele.id);
            else remainders[i-m].push(ele.id);
        }
    }
    printf("%I64d\n%d",ans,arr[0]+add[0]);
    for(int i=1;i<n;++i) printf(" %d",arr[i]+add[i]);
    printf("\n");
    return 0;
}

E. Reachability from the Capital

给出 n 个点, m 条边的有向图,求要使起点 s 能够到达其它所有的节点,至少需要增加几条边。
1 n 5000 , 0 m 5000 , 1 s n ,不存在重边。

首先将所有与起点连通的节点标记,对于其它节点扫描其能到达的节点个数,按可达节点个数从大到小依次标记该节点和与它可达的节点,已经标号的节点跳过。
注:存在时间复杂度为 O ( n ) 的解法。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
const int maxn=5005;
std::vector<int> g[maxn];
int vis[maxn];
void dfs(int x) {
    vis[x]=true;
    for(int i=0,end=g[x].size();i<end;++i) {
        int v=g[x][i];
        if(!vis[v]) dfs(v);
    }
}
struct element {int id,cnt;};
inline int cmp(const element &x,const element &y) {return x.cnt>y.cnt;}
int vis2[maxn],cnt=0;
void dfs2(int x) {
    vis2[x]=true;++cnt;
    for(int i=0,end=g[x].size();i<end;++i) {
        int v=g[x][i];
        if(!vis2[v]) dfs2(v);
    }
}
int main() {
    int n,m,s;
    scanf("%d%d%d",&n,&m,&s);
    int u,v;
    while(m--) {
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
    }
    dfs(s);
    std::vector<element> vec;
    for(int i=1;i<=n;++i) {
        if(!vis[i]) {
            memset(vis2,0,sizeof(vis2));cnt=0;
            dfs2(i);
            vec.push_back((element){i,cnt});
        }
    }
    std::sort(vec.begin(),vec.end(),cmp);
    int ans=0;
    for(int i=0,end=vec.size();i<end;++i) {
        if(!vis[vec[i].id]) {
            ++ans;
            dfs(vec[i].id);
        }
    }
    printf("%d\n",ans);
    return 0;
}

F. Cards and Joy

给你 n × k 个卡片,每张卡片上都写有数字,将卡片分给 n 个人,使得每个人手中有 k 张卡片。每个人都有自己最喜欢的卡片数字,获得 i 张写有自己最喜欢数字的卡片可以给总答案增加 h [ i ] 的开心值,求最大的总开心值。
1 n 500 , 1 k 10 1 c i , f i , h i 10 5 ,保证 h i 1 < h i ( i 1 )

定义 d p [ i ] [ j ] i 个人共获得自己最喜欢的 j 张卡片的最大开心值。对于每种卡片上的数字,统计最喜欢该数字的人数和写有该卡片的个数,统计即可。

#include <cstdio>
#include <algorithm>
typedef long long int ll;
int c[100005]/*写有i的卡片个数*/,f[100005]/*f[i]:喜欢i的人的个数*/,h[15]/*h[i]:拥有i张自己喜欢的卡片的开心值*/;ll dp[505][5005]/*dp[i][j]:i个人喜欢的有j张卡片最大开心值*/;
int main() {
    int n,k;
    scanf("%d%d",&n,&k);
    int x;
    for(int i=0;i<n*k;++i) {
        scanf("%d",&x);
        ++c[x];
    }
    for(int i=0;i<n;++i) {
        scanf("%d",&x);
        ++f[x];
    }
    for(int i=1;i<=k;++i) scanf("%d",&h[i]);
    for(int i=1;i<=n;++i) {//i个人
        for(int j=1;j<=n*k;++j) {//j张卡片
            for(int kk=0;kk<=k;++kk) {//第i个人的卡片数
                if(j>=kk) dp[i][j]=std::max(dp[i][j],dp[i-1][j-kk]+h[kk]);
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=100000;++i) ans+=dp[f[i]][c[i]];
    printf("%I64d\n",ans);
    return 0;
}

待更。。。

Codeforces Round 489 (Div. 2)

Codeforces Round #488 by NEAR (Div. 2)

Codeforces Round #487 (Div. 2)

Educational Codeforces Round 45 (Rated for Div. 2)

Codeforces Round #486 (Div. 3)

Codeforces Round #485 (Div. 2)

Avito Code Challenge 2018

Educational Codeforces Round 44 (Rated for Div. 2)

Codeforces Round #484 (Div. 2)

Codeforces Round #483 (Div. 2) [Thanks, Botan Investments and Victor Shaburov!]

Codeforces Round #482 (Div. 2)

Codeforces Round #481 (Div. 3)

猜你喜欢

转载自blog.csdn.net/whz2018/article/details/80813375