Codeforces Round #645 Div. 2
比赛链接 https://codeforces.com/contest/1358
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197
C. Celex Update
题意:在给定的图上只能往右或者让下走,求从
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1) 走到
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2) 的路径中不同的和的数量
思路:
- 首先最小值和最大值之间路径都是存在的。
- 从最小值慢慢变化到最大值的过程,就是每次都选择一个大 1 的数。每次都会重新选择一个新的格子,每个格子恰好选到一次。那么答案就是 ( y 2 − y 1 ) × ( x 2 − x 1 ) + 1 (y2-y1)\times (x2-x1)+1 (y2−y1)×(x2−x1)+1
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=4e5+10,mod=1e9+7;
int t;
ll a1,b1,a2,b2;
int main()
{
cin>>t;
while(t--)
{
cin>>a1>>b1>>a2>>b2;
cout<<(a2-a1)*(b2-b1)+1<<"\n";
}
return 0;
}
D. The Best Vacation
题意:一共有 n 个月,每个月有
d
i
d_i
di天,每天的权值是自己在当前月份的天数,选择 x 个连续的权值(可以延续到下一年)。求最大的权值之和
思路:枚举每个月的月末往前取 x 天即可。
- 比赛的时候也有想过这样是不是最优的,只要稍微推一下就知道确实是最优的。
- 比如, d 1 = 7 d_1=7 d1=7, d 2 = 6 d_2=6 d2=6 可以表示成:1 2 3 4 5 6 7 1 2 3 4 5 6 。假设选择的区间为 3 4 5 6 7 1 2 3 。这样往后推是递增的,那么最大值就是选择下个月为月末:6 7 1 2 3 4 5 6。
- 如果当前选择的区间为 3 4 5 6 7 1 2,那么还不如从 7 的位置往前选。就是以当前月为月末
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=4e5+10,mod=1e9+7;
int n;
ll x;
ll d[maxn];
ll pref[maxn];
ll cnt[maxn];
int main()
{
scanf("%d%lld",&n,&x);
for(int i=1;i<=n;++i)
{
scanf("%lld",&d[i]);
d[i+n]=d[i];
}
reverse(d+1,d+1+2*n);
for(int i=1;i<=n;++i)
pref[i]=pref[i+n]=(1+d[i])*d[i]/2;
for(int i=1;i<=2*n;++i)
pref[i]+=pref[i-1];
for(int i=1;i<=2*n;++i)
cnt[i]=cnt[i-1]+d[i];
ll ans=0;
for(int i=1;i<=2*n;++i)
{
int p=upper_bound(cnt+1,cnt+1+2*n,cnt[i-1]+x)-cnt-1;
if(p==2*n)
continue;
ll res=pref[p]-pref[i-1];
ll t= x -(cnt[p]-cnt[i-1]);
ll l=d[p+1],r=d[p+1]-t+1;
ll tmp=(l+r)*(l-r+1)/2;
res+=tmp;
ans=max(ans,res);
}
printf("%lld\n",ans);
return 0;
}
E. Are You Fired?
题意:给定一个长度为 n 的数组,后面 n/2个元素相同,选择一个 k ,使得所有长度为 k 的区间各自的和都大于 0 。输出这个 k ,不存在则输出 -1
思路:
- 前面都是任意的,只有后面的元素相同。那么就对后面的元素 x 的正负做讨论
- 如果 x 大于 0,可以试想一下选择的 k 从小到大变化,那么肯定是 k = n 的时候最优,x 等于 0 同理
- 如果 x 小于 0,那么 k 至少是 n/2 +1,因为后面的 n/2个元素都小于 0 了。那么就枚举一下 k 的长度,只需要计算长度为 k 的区间的最小值大于 0 即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5e5+10,mod=1e9+7;
int n;
int a[maxn];
ll sum[maxn];
int main()
{
scanf("%d",&n);
for(int i=1;i<=(n+1)/2;++i) scanf("%d",&a[i]);
int x;
scanf("%d",&x);
for(int i=(n+1)/2+1;i<=n;++i) a[i]=x;
for(int i=1;i<=n;++i)
sum[i]=sum[i-1]+a[i];
if(x>=0)
{
if(sum[n]>0) printf("%d\n",n);
else puts("-1");
return 0;
}
ll mi=9e18;
for(int i=1;i<=(n+1)/2;++i)
{
ll res=sum[n]-sum[i-1];
mi=min(mi,res);
if(mi>0)
{
printf("%d\n",n-i+1);
return 0;
}
mi-=x;
}
puts("-1");
return 0;
}