A. Square
大意
给出一个矩形四个顶点坐标,计算面积
分析
计算行的差乘列的差即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int main()
{
int t;cin>>t;
while(t--)
{
ll a,b;
ll x1=-1e9,x2=1e9;
ll y1=-1e9,y2=1e9;
for(int i=1;i<=4;i++)
{
cin>>a>>b;
x1=max(x1,a);
x2=min(x2,a);
y1=max(y1,b);
y2=min(y2,b);
}
cout<<(x1-x2)*(y1-y2)<<endl;
}
return 0;
}
B. Arranging Cats
大意
给定一个初始串和目标串,最少经过多少次以下操作可以将原串变为目标串
1. 将1变为0
2. 将0变为1
3. 交换0和1
分析
可以发现1,2操作每次最多只能将一个位置变为目标状态,3交换操作每次最多可以将两个位置变为目标状态,所以优先执行3交换操作,不能执行交换操作之后再执行1,2操作。而对于本来就和目标状态一致的位置则没有必要操作,所以我们记录原串和目标串和目标状态不同的位置个数,可以分为两种:
n1.原串是1,需要变成0的
n2.原串是0,需要变成1的
最多交换的次数即min(n1,n2),执行完交换操作之后,还有abs(n1-n2)个位置需要执行1,2操作
则答案=min(n1,n2)+abs(n1-n2)=max(n1,n2)
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int main()
{
int t;cin>>t;
while(t--)
{
int n;
string s,ss;
cin>>n>>s>>ss;
ll n1=0,n0=0;
for(int i=0;i<n;i++)
{
if(s[i]=='1' && ss[i]=='0') n1++;
if(s[i]=='0' && ss[i]=='1') n0++;
}
cout<<max(n1,n0)<<endl;
}
return 0;
}
C. Sending Messages
大意
斯捷潘是个大忙人。今天,他需要在时刻 m1,m2,…mn ( mi<mi+1)发送 n条消息。不幸的是,此刻 ,他的手机只剩下 f 单位的电量。此时 ,手机处于开机状态。手机每开机 a 个单位时间,将损失 a 个单位的电量。此外,Stepan可以随时关闭手机,稍后再打开。
这个动作每次消耗 b个单位的能量。将打开和关闭视为即时,因此您可以在时刻 x 打开它,并在同一时刻发送消息,反之亦然。在时刻 x 发送消息,并在同一时刻关闭手机。如果在任何点电量水平下降到 0 (变为 ≤0 ),则不可能在该时刻发送消息。
由于所有信息对Stepan来说都非常重要,他想知道是否可以在不给手机充电的情况下发送所有信息。
分析
贪心,对于每一段时间一直开机到发送消息时刻所耗电量和一直关机到发送消息时刻的所耗电量取最小值累加即最小耗电量
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=2e5+10;
ll f[N];
ll n,m,a,b;
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n>>m>>a>>b;
for(int i=1;i<=n;i++) cin>>f[i];
ll ans=0;
for(int i=1;i<=n;i++)
{
ans+=min((f[i]-f[i-1])*a,b);
}
if(ans>=m) puts("NO");
else puts("YES");
}
return 0;
}
D. Very Different Array
大意
给定一个包含n个元素的数组a,与一个包含m个元素的数组b(m>=n),从b数组中选出n个元素组成新的数组,并使b数组与a数组对应位置元素之差的和最大,输出这个最大的累加差值
分析
贪心策略,每一步的最优解一定在a的最大值-b的最小值与b的最大值-a的最小值之中产生,每一个数组都用双指针维护端点值即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=2e5+10;
ll a[N],b[N];
int n,m;
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n>>m;
ll ans=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i];
sort(a+1,a+n+1);
sort(b+1,b+m+1,greater<ll>());
ll la=1,ra=n,lb=1,rb=m;
for(int i=1;i<=n;i++)
{
if(abs(a[la]-b[lb])>abs(a[ra]-b[rb]))
{
ans+=abs(a[la]-b[lb]);
la++;
lb++;
}
else
{
ans+=abs(a[ra]-b[rb]);
ra--;
rb--;
}
}
cout<<ans<<endl;
}
return 0;
}
E. Eat the Chip
大意
a和b在玩棋盘游戏,两人各一颗棋子,a的棋子只能向下,左下,右下走,b的棋子只能向上,左上,右上走。a先走,当两人的棋子被吃或有一人的棋子到达边界时游戏结束,输出胜利一方的名字或平局Draw
分析
博弈论+分类讨论
1.由于a只能向下走,b只能向上走,当两人的棋子初始位置在同一行或a的棋子在b的棋子下面,只能产生平局
2.可以获胜的一方由棋子初始位置决定,想获胜就必须产生吃棋子的动作,也就是两人到达同一行时,这一步由谁来走,只有走这一步的人才有获胜的资格,因为a先走,所以两人棋子行坐标之差为奇数时a可以赢,行坐标之差为偶数时b可以赢。
3.由于每局的可获胜方在一开始就决定了,对于另一方的最优结局就是平局,为了不让对方赢,其一定选择远离对方的棋子,即一直向对方棋子的另一侧走,而可以获胜的一方一定选择追对方棋子。但由于棋盘是有边界的,当逃跑的一方到达棋盘边界时,就只能向前走,倘若此时追击一方的棋子还在前方(两人的棋子还没有经过同一行,一方获胜必然在两人棋子处在同一行时发生),则一定会被追上。所以当两人处在同一行时,若追击方所能达到的列数大于等于逃跑方所能达到的列数时,追击方赢;反之逃跑方成功逃跑,平局。
所以对于不是一开始就决定了平局的情况,我们分类讨论可获胜方是谁,并计算追击方与逃跑方相遇时两人所在的列,分类讨论结果即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int main()
{
int t;cin>>t;
while(t--)
{
int n,m,ra,ca,rb,cb;
cin>>n>>m>>ra>>ca>>rb>>cb;
if(ra>=rb) //一开始就背道而驰,必定平手
{
puts("Draw");
continue;
}
int p=(rb-ra)/2;//两人到达同一行需要多少回合
if((rb-ra)%2)//一定是a赢或平手
{
if(ca<cb)//a在b的左边,b为了平手只能向右逃
{
int a=min(ca+p+1,m);//两人在同一行时a所在的列,奇数回合a多走一步
int b=min(cb+p,m);
if(a>=b) puts("Alice");
else puts("Draw");
}
else//a在b的右边,b只能向左逃
{
int a=max(ca-p-1,1);
int b=max(cb-p,1);
if(a<=b) puts("Alice");
else puts("Draw");
}
}
else//一定是b赢或平手
{
if(cb<ca)//b在a的左边,a为了平手只能向右逃
{
int a=min(ca+p,m);/
int b=min(cb+p,m);
if(b>=a) puts("Bob");
else puts("Draw");
}
else
{
int a=max(ca-p,1);
int b=max(cb-p,1);
if(b<=a) puts("Bob");
else puts("Draw");
}
}
}
return 0;
}
下午英语期末,忙里偷闲写一篇,前两场的放假之后再补,加油