A - Park Lighting CodeForces - 1358A
每个路灯最多照亮两个区域,则使尽可能多的路灯这样。每行用行2灯照亮,若每行有一个区域空余,则
用竖2路灯照亮
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int a,b;
cin>>a>>b;
int sum1=a/2;
if(a%2!=0)
{
sum1*=b;
sum1+=b%2+b/2;
}
else
{
sum1*=b;
}
int sum2=b/2;
if(b%2!=0)
{
sum2*=a;
sum2+=a%2+a/2;
}
else
{
sum2*=a;
}
cout<<min(sum1,sum2)<<endl;
}
//system("pause");
return 0;
}
B - Maria Breaks the Self-isolation CodeForces - 1358B
先排序,若同时招i个人,则arr[i-1]处应大于i,找到最大i即可
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int a;
cin>>a;
int sum=1;
int arr[a];
for(int i=0;i<a;i++)
{
cin>>arr[i];
}
sort(arr,arr+a);
for(int i=0;i<a;i++)
{
if(arr[i]<=i+1)
{
sum=i+2;
}
}
cout<<sum<<endl;
}
//system("pause");
return 0;
}
C - Celex Update CodeForces - 1358C
分析可知,路径和有一个最大值和最小值,且之间的值都存在,则最大-最小+1即是结果。而可以发现,先走下,
走完再走右是最大值,先走右,最后下则最小。差为行差×列差
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
cin>>n;
while(n--)
{
ll a,b,c,d;
int cc,dd,aa;
cin>>a>>b>>c>>d;
ll sum=1;
sum+=(c-a)*(d-b);
cout<<sum<<endl;
}
//system("pause");
return 0;
}
D - The Best Vacation CodeForces - 1358D
分析可知应用尺取法,枚举终点推出起点计算拥抱合取最大即可,但存在2个问题:
1.不能把每个月份的具体每天拥抱次数记下来。(数量太大,数组存不下)
2.可以取不同年份的连续月(会出现回环)
对应的解决方法:
1.分析可知,最大拥抱数一定以某月的最后一天为终点,则可以只记录每月天数和每月总拥抱次数(使用时:如
该月有5天,取两天,则从1到5的合中刨去1到5-2的和)(另外,月份如果记录为前i个月的和,则ij相减就
可以得到i到j月的总天数,拥抱数也可以如此记录)
2.将每月天数存两遍(从1到2n),这样终点从2n遍历至n时,推出的起点不用取环
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e6+100;
LL a[N],sum[N];
LL cal(LL l,LL r)
{
return (l+r)*(r-l+1)/2;
}
int main()
{
int n;
LL x;
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i+n]=a[i];//记录两遍天数,这样不用计算回环
sum[i]=sum[i+n]=cal(1,a[i]);//每一个月拥抱的总次数
}
for(int i=1;i<=2*n;i++)
{
a[i]+=a[i-1];
sum[i]+=sum[i-1];
}
LL ans=0;
for(int i=2*n,j=2*n;i>n;i--)//枚举终点
{
while(j>0&&a[i]-a[j]<=x)
j--;
ans=max(ans,sum[i]-sum[j]-cal(1,a[i]-a[j]-x));
}
cout<<ans<<endl;
//system("pause");
return 0;
}
启示:1.利用两遍记录防止回环 2.记录时,数组第i个位置记录前i个和,这样可以快速求某区间数组的和
待补充ing