Educational Codeforces Round 108 (Rated for Div. 2)
A. Red and Blue Beans
题意:有红豆r个,蓝豆b个,每次分配
r
i
r_i
ri个红豆和
b
i
个
蓝
豆
b_i个蓝豆
bi个蓝豆打包且保证
r
i
和
b
i
r_i和b_i
ri和bi都大于等于1且保证
∣
r
i
−
b
i
∣
<
=
d
|r_i-b_i|<=d
∣ri−bi∣<=d,问能否恰好把所有红豆蓝豆打包完
题解:极端的假设,保证r<b的情况下,当
r
i
=
1
r_i=1
ri=1时,
b
i
<
=
d
+
1
b_i<=d+1
bi<=d+1,每次最多可以减少
d
d
d的差值,所以只要保证
b
−
r
<
=
d
∗
r
b-r<=d*r
b−r<=d∗r;在r>=b情况下同理。
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define ll long long
signed main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
ll r,b,d;cin>>r>>b>>d;
ll mi=min(r,b)*d;
if(abs(r-b)>mi)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
B. The Cake Is a Lie
题意:矩阵,往右(x,y+1)走则权值加上横坐标x,往下走(x+1,y)则权值加上纵坐标y,问从(1,1)出发达到(n,m)的权值是不是K?
题解:可以手算确定,到达每个点的权值是一定即n-1+n*(m-1)
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define ll long long
signed main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
ll n,m,k;cin>>n>>m>>k;
if(n-1+n*(m-1)==k)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
C. Berland Regional
题意:n个学生,分别来自学校
u
i
u_i
ui,且每个学生都有编程能力
s
i
s_i
si。每个学校每次选择学生组成一个k人的队伍参赛时,都让
s
i
s_i
si较大的k个人组在一起,同个学校可以派出多个队伍且保证每个队友恰好有k个人。问k=1,2,3…n时,求出所有学校派出学生组队参赛的所有
∑
s
i
\sum{s_i}
∑si
题解:把每个学生存到对应的学校,并按照从大到小降序存进数组u[],且对每个学校的该大小位size的数组进行前缀和s[],每个学校对
a
n
s
k
ans_k
ansk的贡献是前size-k%size个的前缀和
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define ll long long
const int N=2e5+7;
set<ll>st;
vector<ll>u[N];
bool cmp(pair<ll,ll>a,pair<ll,ll>b){
return a.first>b.first;
}
signed main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
int n;cin>>n;
vector<pair<ll,ll>>p(n);
vector<ll>ans(n+2,0); st.clear();
for(int i=0;i<n+1;i++)u[i].clear();
for(int i=0;i<n;i++)cin>>p[i].second,st.insert(p[i].second);
for(int i=0;i<n;i++)cin>>p[i].first;
sort(p.begin(),p.end(),cmp);
for(int i=0;i<n;i++)u[p[i].second].push_back(p[i].first);
for(auto i:st){
int siz=u[i].size();
for(int j=1;j<siz;j++)u[i][j]+=u[i][j-1];
for(int j=1;j<=siz;j++)ans[j]+=u[i][siz-1-siz%j];//关键是这里处理ans[]
}
for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
cout<<endl;
}
return 0;
}
D. Maximum Sum of Products
题意:可以至多反转一次a[],问最大的
∑
a
i
∗
b
i
\sum{a_i*b_i}
∑ai∗bi
题解:T=2s,n=5000,直接枚举所有情况,所以考虑ai*bi的前缀和,枚举中点,且考虑翻转的长度奇偶,把翻转的[l,r]和[l-1,r+1]的式子展开发展不同点只有a[l-1]*b[r+1]+a[r+1]*b[l-1],左右两端用前缀和求和即可
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define ll long long
ll a[5005],b[5005],s[5005],ans=0;
int n;
void run1(int x){ //翻转长度位奇数
ll res=0;
for(int l=x,r=x;l>=1&&r<=n;l--,r++){
if(l==r) res+=a[l]*b[l];
else res+=a[l]*b[r]+a[r]*b[l];
ans=max(ans,res+s[l-1]+s[n]-s[r]);
}
}
void run2(int x){ //翻转长度位偶数
ll res=0;
for(int l=x,r=x+1;l>=1&&r<=n;l--,r++){
if(l==r) res+=a[l]*b[l];
else res+=a[l]*b[r]+a[r]*b[l];
ans=max(ans,res+s[l-1]+s[n]-s[r]);
}
}
signed main(){
ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int j=1;j<=n;j++)cin>>b[j];
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i]*b[i];
for(int i=1;i<=n;i++)run1(i); //翻转长度位奇数
for(int i=1;i<=n;i++)run2(i); //翻转长度位偶数
ans=max(ans,s[n]); //特判一下原来不翻转
cout<<ans;
return 0;
}