总结写在前头准没错,今天比赛前也有好好睡觉,可能起太晚了,一开始思维没活跃起来。
然后就是C的实现一言难尽,知道应该用vector开二维,但真不熟:(
外加没开ll加数组开小了:(
菜死了菜死了
A. Red and Blue Beans
题意: 你有红色球n个,蓝色球m个,假设你可以用无数个背包,每个背包里最少放一个红球和篮球,求背包中红色球和蓝色球相差最大个数的最小值。
思路:模拟着放,每个包都尽量按比例放n/m,然后判断差是否在K以内。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,i,j,n;
cin>>t;
while(t--){
int a,b,c;
cin>>a>>b>>c;
int ans=max(a,b)%min(a,b)==0?max(a,b)/min(a,b):max(a,b)/min(a,b)+1;
if(ans-1<=c){scYES;}
else scNO;
}
return 0;
}
B. The Cake Is a Lie
题意:起点是(1,1),有两种走法,一种是向右走,需要和横坐标一样大的花费,一种是向下走,需要和纵坐标一样大的花费,求最后的花费是否为k。
思路:其实一开始就觉得它的花费是定值,然后推花费的时候推错了,其实既然怎么走都是一样的花费,那我就走一条路求花费就行了,看别人的式子那么简单就一行就我模拟跑的
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,i,j;
cin>>t;
while(t--){
int n,m,k;
cin>>n>>m>>k;
int ans1=0;
for(i=1;i<=n-1;i++){
ans1+=1;
}
for(j=1;j<=m-1;j++){
ans1+=i;
}
if(ans1==k){
scYES;
}
else {
scNO;
}
}
return 0;
}
C. Berland Regional
题意:有n位同学,分别来自不同的学校,有不同的编程水平,每个学校可以派出n个队,求当每个队人数为k时,每个学校派出的队伍的编程水平总和。
思路:首先开个结构体先按照学校排序再按分数排,观察规律,不难发现如果学校的人数%每个队的人数=0时,即可全员出动,那么ans【k】就等于学校总人数的和,否则,每个队都会剩下一部分人无法组队,然后按照学校遍历,再按照人数遍历对答案有贡献的值即可(就是能派出的队伍),估摸着复杂度不会t,还可以用前缀和优化一下。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2*1e5+100000;
struct node {
int u;
int s;
}mo[maxn];
int u[maxn];
int ans[maxn];
int sum[maxn];
bool cmp(node a,node b){
if(a.u==b.u){
return a.s>b.s;
}
else {
return a.u<b.u;
}
}
signed main()
{
int t,i,j,n,q;
scanf("%lld",&t);
while(t--){
memset(ans,0,sizeof(ans));
map<int ,int >m1;
scanf("%lld",&n);
for(i=0;i<n;i++){
scanf("%lld",&u[i]);
mo[i].u=u[i];
m1[u[i]]++;
}
for(i=0;i<n;i++){
scanf("%lld",&mo[i].s);
}
sort(mo,mo+n,cmp);
int cnt=1;
for(i=0;i<n;){
int js=m1[cnt++];
sum[0]=0;
for(int d1=0;d1<js;d1++) {
sum[d1+1]=sum[d1]+mo[i+d1].s;
}
for(int k=1;k<=js;k++){
if(js%k==0) ans[k]+=sum[js];
else ans[k]+=sum[(js/k)*k];
}
i+=js;
}
for( q=1;q<=n-1;q++){
printf("%lld ",ans[q]);
}
printf("%lld\n",ans[q]);
}
return 0;
}
D. Maximum Sum of Products
题意:给你两个数组a和b,它的总价值是相同位置相乘的和(a1×b1+a2×b2…这样),然后可以操作一次,翻转a数列的一个子区间,问翻转哪段子区间可以得到最大的价值。
思路:大佬说像区间dp,其实有点类似之前校赛做过的一道题,其实就是先选定一个点,然后扩大他们的左区间和右区间长度,那么他的翻转其实只有最外面的改变了
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=5005;
signed main()
{
int n,i,j,k,a[maxn],b[maxn],sum=0;
cin>>n;
for(i=0;i<n;i++) cin>>a[i];
for(i=0;i<n;i++) cin>>b[i];
for(i=0;i<n;i++) sum+=a[i]*b[i];
int ans=sum;
for(i=0;i<n;i++){
int m1=sum;
for(j=i-1,k=i+1; (j<n&&j>=0)&&(k<n&&k>=0); j--,k++){
m1-=a[j]*b[j]+a[k]*b[k];
m1+=a[j]*b[k]+a[k]*b[j];
ans=max(ans,m1);
}
m1=sum;
for( j = i, k = i + 1; (j<n&&j>=0)&&(k<n&&k>=0); j--, k++){
m1 -= a[j] * b[j] + a[k] * b[k];
m1 += a[j] * b[k] + a[k] * b[j];
ans = max(ans, m1);
}
}
cout<<ans<<endl;
return 0;
}