C. Berland Regional(模拟+vector优化)
Polycarp is an organizer of a Berland ICPC regional event. There are n universities in Berland numbered from 1 to n. Polycarp knows all competitive programmers in the region. There are n students: the i-th student is enrolled at a university ui and has a programming skill si.
Polycarp has to decide on the rules now. In particular, the number of members in the team.
Polycarp knows that if he chooses the size of the team to be some integer k, each university will send their k strongest (with the highest programming skill s) students in the first team, the next k strongest students in the second team and so on. If there are fewer than k students left, then the team can’t be formed. Note that there might be universities that send zero teams.
The strength of the region is the total skill of the members of all present teams. If there are no teams present, then the strength is 0.
Help Polycarp to find the strength of the region for each choice of k from 1 to n.
Input
The first line contains a single integer t (1≤t≤1000) — the number of testcases.
The first line of each testcase contains a single integer n (1≤n≤2⋅105) — the number of universities and the number of students.
The second line of each testcase contains n integers u1,u2,…,un (1≤ui≤n) — the university the i-th student is enrolled at.
The third line of each testcase contains n integers s1,s2,…,sn (1≤si≤109) — the programming skill of the i-th student.
The sum of n over all testcases doesn’t exceed 2⋅105.
Output
For each testcase print n integers: the strength of the region — the total skill of the members of the present teams — for each choice of team size k.
Example
inputCopy
4
7
1 2 1 2 1 2 1
6 8 3 1 5 1 5
10
1 1 1 2 2 2 2 3 3 3
3435 3014 2241 2233 2893 2102 2286 2175 1961 2567
6
3 3 3 3 3 3
5 9 6 7 9 7
1
1
3083
outputCopy
29 28 26 19 0 0 0
24907 20705 22805 9514 0 0 0 0 0 0
43 43 43 32 38 43
3083
Note
In the first testcase the teams from each university for each k are:
k=1:
university 1: [6],[5],[5],[3];
university 2: [8],[1],[1];
k=2:
university 1: [6,5],[5,3];
university 2: [8,1];
k=3:
university 1: [6,5,5];
university 2: [8,1,1];
k=4:
university 1: [6,5,5,3];
题解:这个题感觉比较复杂,毕竟也是cf div2 c题难度,看到题目首先想到了结构体,再加上sort排序,但是超时了:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=2e5+5;
struct node{
ll x;
ll y;
}a[nl];
bool cmp(node a,node b){//将每个学校的同学按递减顺序排在一起
if(a.x!=b.x){
return a.x<b.x;
}else{
return a.y>b.y;
}
}
int main(){
ll t;
cin>>t;
ll i,j;
while(t--){
ll n;
cin>>n;
for(i=0;i<n;i++){
cin>>a[i].x;
}
for(i=0;i<n;i++){
cin>>a[i].y;
}
ll num=0;
ll k=1;
sort(a,a+n,cmp);
for(i=1;i<n;i++){//找到最长学校的学生
if(a[i].x==a[i-1].x){
k++;
}else{
if(k>num){
num=k;
}
k=1;
}
}
if(k>num){
num=k;
}
for(i=1;i<=num;i++){//这里会超时。
ll sum=0;
ll su=0;
ll f=1;
for(j=0;j<n;j++){
su+=a[j].y;
if(f%i==0){//如果能整除,直接加到sum中
sum+=su;
f=1;
su=0;
}else{
if(a[j].x==a[j+1].x){//如果前后相等说明是同一学校的。
f++;
}else{//如果不是则使su归零
f=1;
su=0;
}
}
}
if(i==1){
cout<<sum;
}else{
cout<<" "<<sum;
}
}
for(i=num+1;i<=n;i++){
cout<<" "<<"0";
}
cout<<endl;
}
}
后来上网上寻求大佬帮助,用了vector数组优化:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=2e5+5;//这里忘记改成2e5好几次,因为平常习惯写1e5.
vector<ll>v[nl];
struct node{
ll num;
ll x;
}vl[nl];
bool cmp(node a,node b){只是按照能力值递减排序
if(a.x!=b.x){
return a.x>b.x;
}
}
ll a[nl],b[nl],c[nl],d[nl];
ll ans[nl];
int main(){
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
ll i,j;
ll k=0;
for(i=0;i<n;i++){
cin>>vl[i].num;
ll y;
y=vl[i].num;
if(a[y]==0){
a[y]++;//判断该学校是否出现过
b[k++]=y;//如果未出现则标记一下,后面会用到
}
}
for(i=0;i<n;i++){
cin>>vl[i].x;
}
sort(vl,vl+n,cmp);
for(i=0;i<n;i++){
ll y=vl[i].num;
c[y]++;//记录一个学校有多少学生
d[y]+=vl[i].x;//一个一个记录学校学生的能力值
v[y].push_back(d[y]);//这里是为了后面,对于如果一个学校可以有多少学生上场
}
for(i=0;i<k;i++){
for(j=0;j<v[b[i]].size();j++){
ans[j]+=v[b[i]][c[b[i]]/(j+1)*(j+1)-1];///b[i]即在这里用到了,先除以(j+1)因为要判断可以派出几个队伍,再乘(j+1),要算出共有几人,减一是因为数组 从零开始记录的
}
}
for(i=0;i<n;i++){
cout<<ans[i]<<" ";
}
for(i=0;i<n;i++){
cout<<endl;
}
for(i=0;i<n+1;i++){
v[i].clear();//清空vector数组
a[i]=0,b[i]=0,c[i]=0,d[i]=0;
ans[i]=0;//数组归零
}
}
}
B. Morning Jogging
The 2050 volunteers are organizing the “Run! Chase the Rising Sun” activity. Starting on Apr 25 at 7:30 am, runners will complete the 6km trail around the Yunqi town.
There are n+1 checkpoints on the trail. They are numbered by 0, 1, …, n. A runner must start at checkpoint 0 and finish at checkpoint n. No checkpoint is skippable — he must run from checkpoint 0 to checkpoint 1, then from checkpoint 1 to checkpoint 2 and so on. Look at the picture in notes section for clarification.
Between any two adjacent checkpoints, there are m different paths to choose. For any 1≤i≤n, to run from checkpoint i−1 to checkpoint i, a runner can choose exactly one from the m possible paths. The length of the j-th path between checkpoint i−1 and i is bi,j for any 1≤j≤m and 1≤i≤n.
To test the trail, we have m runners. Each runner must run from the checkpoint 0 to the checkpoint n once, visiting all the checkpoints. Every path between every pair of adjacent checkpoints needs to be ran by exactly one runner. If a runner chooses the path of length li between checkpoint i−1 and i (1≤i≤n), his tiredness is
mini=1nli,
i. e. the minimum length of the paths he takes.
Please arrange the paths of the m runners to minimize the sum of tiredness of them.
Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤10000). Description of the test cases follows.
The first line of each test case contains two integers n and m (1≤n,m≤100).
The i-th of the next n lines contains m integers bi,1, bi,2, …, bi,m (1≤bi,j≤109).
It is guaranteed that the sum of n⋅m over all test cases does not exceed 104.
Output
For each test case, output n lines. The j-th number in the i-th line should contain the length of the path that runner j chooses to run from checkpoint i−1 to checkpoint i. There should be exactly m integers in the i-th line and these integers should form a permuatation of bi,1, …, bi,m for all 1≤i≤n.
If there are multiple answers, print any.
Example
inputCopy
2
2 3
2 3 4
1 3 5
3 2
2 3
4 1
3 5
outputCopy
2 3 4
5 3 1
2 3
4 1
3 5
Note
In the first case, the sum of tiredness is min(2,5)+min(3,3)+min(4,1)=6.
In the second case, the sum of tiredness is min(2,4,3)+min(3,1,5)=3.
题解:本题较好理解,操作上可能有些困难,将所有数中最小的前m个数排列在不同列中即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=1e2+5;
vector<ll>a[nl];
ll b[nl*nl];
ll c[nl*nl];
ll d[nl*nl]={0};
ll p[nl*nl];
int main(){
ll t;
cin>>t;
while(t--){
ll n,m;
cin>>n>>m;
ll i,j;
ll k=0;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
cin>>b[k];//先存在一维数组中,方便排序
k++;
a[i].push_back(b[k-1]);//放在vector数组中,方便逐行操作
}
}
sort(b,b+n*m);
k=0;
ll f=0;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
for(ll z=0;z<m;z++){
if(a[i][j]==b[z]&&p[z]==0){//这里很细节,每次比较成功后都要把z位置标记,避免重复。
p[z]=1;
c[i]++;//记录这一行有多少个数在前m个数中
k++;
break;
}
}
if(k==m){
break;
}
}
if(f==1){
break;
}
}
f=0;
k=0;
for(i=0;i<n;i++){
for(ll z=0;z<m;z++){
d[z]=a[i][z];//放入一个新的数组,方便排序,注意sort(a[i],a[i]+m)是不允许的。
}
if(c[i]>=1){
sort(d,d+m);
for(ll z=0;z<k;z++){//先从第c[i]+1个输出,共输出k个,k是由前面输出的最小值个数决定。
cout<<d[z+c[i]]<<" ";
}
for(ll z=0;z<c[i];z++){//在输出最小的c[i]个
cout<<d[z]<<" ";
}
for(ll z=k+c[i];z<m;z++){//在输出后面k+a[i]个
cout<<d[z]<<" ";
}
cout<<endl;
k+=c[i];
}else{
for(j=0;j<m;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
for(i=0;i<n;i++){
a[i].clear();//每次都要清空数组,不然会报错。
c[i]=0;
}
for(i=0;i<m;i++){
p[i]=0;
}
}
}
题目总结:1.知道了vectora[nl]中,sort(a[i],a[i]+n)操作不允许,但是二维数组可以。
2.数组多的题目,不要忘记清空数组。
CodeForces - 151B
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=1e5+5;
struct node{
ll a,b,c;
ll ad;
string s;
}no[nl];
bool cmp1(node al,node bl){
if(al.a!=bl.a){
return al.a>bl.a;
}else{
return al.ad<bl.ad;
}
}
bool cmp2(node al,node bl){
if(al.b!=bl.b){
return al.b>bl.b;
}else{
return al.ad<bl.ad;
}
}
bool cmp3(node al,node bl){
if(al.c!=bl.c){
return al.c>bl.c;
}else{
return al.ad<bl.ad;
}
}
int main(){
ll t;
cin>>t;
ll i,j;
for(i=0;i<t;i++){
ll n;
cin>>n;
no[i].ad=i;
cin>>no[i].s;
while(n--){
string sl;
cin>>sl;
if(sl[0]==sl[1]&&sl[0]==sl[3]&&sl[0]==sl[4]&&sl[0]==sl[6]&&sl[0]==sl[7]){
no[i].a++;
}else if(sl[0]>sl[1]&&sl[1]>sl[3]&&sl[3]>sl[4]&&sl[4]>sl[6]&&sl[6]>sl[7]){
no[i].b++;
}else{
no[i].c++;
}
}
}
sort(no,no+t,cmp1);
cout<<"If you want to call a taxi, you should call: ";
cout<<no[0].s;
for(i=1;i<t;i++){
if(no[i].a==no[0].a){
cout<<", "<<no[i].s;
}
}
cout<<"."<<endl;
sort(no,no+t,cmp2);
cout<<"If you want to order a pizza, you should call: ";
cout<<no[0].s;
for(i=1;i<t;i++){
if(no[i].b==no[0].b){
cout<<", "<<no[i].s;
}
}
cout<<"."<<endl;
sort(no,no+t,cmp3);
cout<<"If you want to go to a cafe with a wonderful girl, you should call: ";
cout<<no[0].s;
for(i=1;i<t;i++){
if(no[i].c==no[0].c){
cout<<", "<<no[i].s;
}
}
cout<<"."<<endl;
}