Educational Codeforces Round 108 (Rated for Div. 2) C. Berland Regional

翻译:

Polycarp是伯兰ICPC区域活动的组织者。伯兰有𝑛所大学,编号从1到𝑛。波利卡普认识这个地区所有有竞争力的程序员。有𝑛学生:𝑖-th学生在大学注册𝑢𝑖,有编程技能𝑠𝑖。

Polycarp现在必须决定规则。特别是团队成员的数量。

波利卡普知道,如果他选择团队的规模为某个整数𝑘,每个大学将把他们的𝑘最强(具有最高编程技能的𝑠)的学生派到第一个团队,然后把下一个𝑘最强的学生派到第二个团队,以此类推。如果剩下的学生少于𝑘,那么就不能组建团队。请注意,可能有些大学没有派出任何团队。

该地区的实力是所有参赛队伍成员的技能总和。如果没有队伍在场,那么强度为0。

帮助Polycarp找到每个选择𝑘从1到𝑛的区域的强度。

输入
第一行包含单个整数𝑡(1≤𝑡≤1000)—测试用例的数量。

每个测试用例的第一行包含单个整数𝑛(1≤𝑛≤2⋅105)——大学数量和学生数量。

每个测试用例的第二行包含𝑛整数𝑢1,𝑢2,…,𝑢𝑛(1≤𝑢𝑖≤𝑛)—𝑖-th学生就读的大学。

每个测试用例的第三行包含𝑛整数𝑠1,𝑠2,…,𝑠𝑛(1≤𝑠𝑖≤109)-这是𝑖-th学生的编程技能。

𝑛在所有测试用例上的总和不超过2⋅105。

输出
对于每个测试用例,打印𝑛整数:区域的强度—当前团队成员的总技能—对于每个团队规模的选择𝑘。

例子
inputCopy
4
7
1 2 1 2 1 2 1 2 1
6 8 3 1 5 1 5
10
1 1 1 2 2 2 2 2 3 3 3
3435 3014 2241 2233 2893 2102 2286 2175 1961 2567
6
3 3 3 3 3 3 3 3 3
5 9 6 7 9 7
1
1
3083
outputCopy
29 28 26 19 0 0
24907 20705 22805 9514 0 0 0 0 0 0 0
43 43 43 32 38 43
3083
请注意
在第一个测试用例中,每个𝑘的每个大学的团队是:

𝑘= 1:
大学1:[6],[5],[5],[3];
大学2:[8],[1],[1];
𝑘= 2:
大学1:[6,5],[5,3];
大学2:[8,1];
𝑘= 3:
大学1:[6,5,5];
大学二:[8,1,1];
𝑘= 4:
大学1:[6,5,5,3];

思路:

每个大学都有不同的人数,强度要最强1~n次询问,所以我们要先预处理出来,让每次查询是O1。我们可以排序,然后用前缀和,来记录每个学校的团队,对于多出来的人,最后取余减一下,就能得出来该学校k个人组成的团队的值。然后我们对学校的数量和人数进行遍历,然后让符合的每个都加上,因为n过大,直接遍历肯定会TLE。

代码:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

struct we{
    int x;
    ll y;
}c[200005];
bool cmp(we a,we b){
    return  a.y>b.y;
}
ll an[200005],jj;
vector<ll>q[200005];
void solv(){
    
    cin>>n;
    for (int i =1; i<=n; i++) {
        q[i].clear();
        q[i].push_back(0);
        an[i]=0;
    }
    int xu=-1;
    for (int i =1; i<=n; i++) {
        cin>>c[i].x;
        xu=max(xu, c[i].x);
    }
    for (int i =1; i<=n; i++) {
        cin>>c[i].y;
    }
    sort(c+1, c+1+n, cmp);
    for (int i =1; i<=n; i++) {
            q[c[i].x].push_back(c[i].y+q[c[i].x][q[c[i].x].size()-1]);
        
    }
    for (int i =1; i<=n; i++) {
        for (int k=1; k<=xu; k++) {
            if (q[k].size()<=i) {
                continue;
            }
            if (i==1) {
                an[i]+=q[k][q[k].size()-1];
                continue;
            }
//            printf("%d  %lld \n",i,an[i]);
//            printf("%lld\n",q[k][q[k].size()-q[k].size()%i]);
            an[i]+=q[k][q[k].size()-1-(q[k].size()-1)%i];
//            printf("%d  %lld \n",i,an[i]);
        }
        printf("%lld ",an[i]);
    }printf("\n");
    
    
    
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        solv();
    }
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值