Codeforces Round #786 (Div. 3)-E
题目
解题思路
分类讨论进行暴力求解
- 消除中间距离超过1的两个点,也就是直接消除那么需要的次数为 c e i l ( ( a [ i ] + a [ j ] ) / 2 ) ceil((a[i]+a[j])/2) ceil((a[i]+a[j])/2)
- 消除中间距离正好为1的两个点,也就每次除2,那么直接需要的次数为 c e i l ( ( a [ i ] + a [ i + 2 ] ) / 2 ) ceil((a[i]+a[i+2])/2) ceil((a[i]+a[i+2])/2)
- 消除连续的两个点,这个时候不妨设
x
=
m
a
x
(
a
[
i
]
,
a
[
i
+
1
]
)
,
y
=
m
i
n
(
a
[
i
]
,
a
[
i
+
1
]
)
x=max(a[i],a[i+1]),y=min(a[i],a[i+1])
x=max(a[i],a[i+1]),y=min(a[i],a[i+1]),那么显然可以先进行第一步
(
x
−
y
)
(x-y)
(x−y)次操作,这样之后
x
=
x
−
2
∗
(
x
−
y
)
=
2
∗
y
−
x
,
y
=
y
−
(
x
−
y
)
=
2
∗
y
−
x
x=x-2*(x-y)=2*y-x,y=y-(x-y)=2*y-x
x=x−2∗(x−y)=2∗y−x,y=y−(x−y)=2∗y−x,这个时候两个正好一样了,但是需要先进行前提判断
- 如果 2 ∗ y − x < = 0 2*y-x<=0 2∗y−x<=0,那么就不需要进行了,次数为 c e i l ( x / 2 ) ceil(x/2) ceil(x/2)
- 否则,每次其实是消除3即 c e i l ( ( x + y ) / 3 ) ceil((x+y)/3) ceil((x+y)/3)再加上第一次的 ( x − y ) (x-y) (x−y)次即可
总的来说,最重要的就是分类讨论的思想,以及看清事情的本质
求解代码
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
int d[250001];
int main()
{
ios::sync_with_stdio(false);
int n;
cin>>n;
int min1=0x3f3f3f3f;
int min2=0x3f3f3f3f;
for (int i=0;i<n;i++)
{
cin>>d[i];
if (d[i]<min2)
{
if (d[i]<min1)
{
min2=min1;
min1=d[i];
}
else
min2=d[i];
}
}
ll res1=((min1+1)/2)+(min2+1)/2;
//分三种情况考虑
//消灭两个中间隔1的点
ll res2=0x3f3f3f3f;
for (int k=0;k<n-2;k+=1)
{
ll temp=(d[k]+d[k+2]+1)/2;
if (temp<res2)
res2=temp;
}
//消灭两个连续的点
ll res3=0x3f3f3f3f;
for (int k=0;k<n-1;k++)
{
ll x=max(d[k],d[k+1]);
ll y=min(d[k],d[k+1]);
ll temp=0;
if (2*y<=x)
{
temp=(x+1)/2;
}
else
{
temp+=(x-y);
temp+=((2*y-x)*2+2)/3;
}
if (temp<res3)
res3=temp;
}
ll res=min(res1,res2);
res=min(res,res3);
cout<<res<<endl;
system("pause");
return 0;
}