博客主页:PH_modest的博客主页
当前专栏:CF比赛记录
其他专栏:
每日一题
cf闯关练习
C语言跬步积累
座右铭:广积粮,缓称王!
直接暴力每个点直接的距离,然后排个序,排序后的结果为:宽、宽、长、长、斜边、斜边,第一个和第三个就是宽和长,因为一个点和另外几个点组成的边分为三种:宽、长、斜边。根据斜边大于宽和长就可以得到前面的结论。
//https://codeforces.com/contest/1921/problem/A
//
//
#include
#define int long long
using namespace std;
int f(int x,int y)
{
return sqrt(x*x+y*y);
}
void solve()
{
int s[8];
int a,aa,b,bb,c,cc,d,dd;
cin>>a>>aa>>b>>bb>>c>>cc>>d>>dd;
s[0]=f(abs(a-b),abs(aa-bb));
s[1]=f(abs(a-c),abs(aa-cc));
s[2]=f(abs(a-d),abs(aa-dd));
s[3]=f(abs(b-c),abs(bb-cc));
s[4]=f(abs(b-d),abs(bb-dd));
s[5]=f(abs(c-d),abs(cc-dd));
sort(s,s+6);
int x=s[0],y=s[2];
cout<<x*y<<"\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
这边不建议使用hypot来求斜边(
我一开始用了之后结果会出错,浪费了我好长时间)
- 结论:分别记录操作一和操作二的次数,最大的就是结果。
- 推导:分别统计需要放入猫的数量(操作一,pt),和需要移除猫的数量(操作二,mov),因为这两个可以合并成一个动作完成(操作三),两个值当中求取一个最小的(minn),这个就是合并成操作三,然后用这两个数的较大值减去较小值就是得到需要单独完成的次数(maxx-minn),两个相加就得到结果了(minn+maxx-minn)。
//https://codeforces.com/contest/1921/problem/B
//
//
#include
#define int long long
using namespace std;
void solve()
{
int n;
cin>>n;
string s,f;
cin>>s>>f;
int mov=0,pt=0;
for(int i=0;i<n;i++)
{
if(s[i]=='1'&&f[i]=='0')
{
mov++;
}
else if(s[i]=='0'&&f[i]=='1')
{
pt++;
}
}
int minn=min(mov,pt);
int maxx=max(mov,pt);
int ans=minn+maxx-minn;
cout<<ans<<"\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
每次可以选择两种操作:
- 操作一:不黑屏,一直亮屏到下一次发消息(x*a)(x表示经过的时间,a表示单位时间失去的电量)
- 操作二:黑屏,到下一次发消息再亮屏(b)(b表示操作二需要花费的电量)
只需要每次发消息前比较一下哪种情况消耗的电量少,最后判断一下电量是否大于0即可
//https://codeforces.com/contest/1921/problem/C
//
//
#include
#define int long long
using namespace std;
int s[200020];
int v[200020];
void solve()
{
int n,f,a,b;
cin>>n>>f>>a>>b;
s[0]=0;
for(int i=1;i<=n;i++)
{
cin>>s[i];
}
for(int i=0;i<n;i++)
{
v[i]=s[i+1]-s[i];
if(v[i]*a<b)
{
f-=(v[i]*a);
}
else
{
f-=b;
}
}
if(f>0) cout<<"YES\n";
else cout<<"NO\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
这种题目很容易想复杂,建议先以简单的情况写,发现结果不对再改,不然很浪费时间
贪心
每次肯定是选差值最大的,差值最大会在两种情况下产生:
- a数组中最大的 - b数组中最小的
- b数组中最大的 - a数组中最小的
所以只需要比较这两个值,取最大值即可
具体操作就是先将两个数组排序,因为是直接判断,顺序对结果没有影响,然后将排好序的数组分别尾插到双端队列中(方便尾删和头删),然后遍历判断即可
//https://codeforces.com/contest/1921/problem/D
//
//
#include
#define int long long
using namespace std;
int a[200020];
int b[200020];
deque<int>s;
deque<int>v;
int ans=0;
int k=0;
int m,n;
void solve()
{
s.clear();
v.clear();
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int i=0;i<m;i++)
{
cin>>b[i];
}
sort(a,a+n);
sort(b,b+m);
for(int i=0;i<n;i++)
{
s.push_back(a[i]);
}
for(int i=0;i<m;i++)
{
v.push_back(b[i]);
}
ans=0;
for(k=0;k<n;k++)
{
if(abs(s.back()-v.front())>abs(v.back()-s.front()))
{
ans+=(abs(s.back()-v.front()));
s.pop_back();
v.pop_front();
}
else
{
ans+=(abs(v.back()-s.front()));
s.pop_front();
v.pop_back();
}
}
cout<<ans<<"\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
CF比赛记录系列旨在记录比赛过程,所以对代码的解释并不会特别详细,但足够引导大家写出来,选的题目都不会特别难,但也不是特别简单,比较考验大家的基础和应用能力,我希望能够将这个系列一直写下去,也希望大家能够和我一起坚持每天写代码。
之后每个星期都会不定期更新codeforces和atcoder上的题目,想要学习算法的友友们千万别错过了,有什么疑问欢迎大家在评论区留言或者私信博主!
在这里送大家一句话:广积粮,缓称王!