A.Cancel the Trains
题意:
横竖都有101条轨道,告诉你两种轨道上都有速度为1的一些火车,问最少取消多少辆使得不出现相撞
题解:
显然判断一下初始会有多少相撞就取消多少辆火车即可。
int _,x,n,m;
int vis[105];
int main() {
for(scanf("%d",&_);_;_--){
n=rd();m=rd();
memset(vis,0,sizeof(vis));
int ans=0;
for (int i=1;i<=n;i++){
x=rd();vis[x]=1;
}
for (int i=1;i<=m;i++){
x=rd();ans+=vis[x];
}
cout<<ans<<endl;
}
return 0;
}
B.Suffix Operations
题意:
每次操作能对一个数列的后缀进行+1或-1,在最多修改一个数字的前提下使得最少的操作次数使得数列每个数全部相等
题解:
我们先考虑没有修改的条件下是多少个操作,显然就是两两数差的绝对值之和。
那单一的一个数对答案的贡献是多少呢?
若数列是这样的
3 2 1
那么显然两次+1操作就行
若数列是这样的
3 4 1
对于中间的4跟之前的2的区别在于,1变化到3经过了2,而不经过4,所以我们需要对于每一个数如果比相邻的数都大或都小,我们可以计算出他带来的答案贡献,判断出最大的之后,用初始答案减去即可。
int main() {
for(scanf("%lld",&_);_;_--){
n=rd();
for (int i=1;i<=n;i++)a[i]=rd();
ll ans=0,mx=0;
for (int i=n-1;i>=1;i--){
ans+=abs(a[i]-a[i+1]);
}
for (int i=1;i<=n;i++){
if (i==1)mx=max(mx,(ll)abs(a[1]-a[2]));
else if (i==n)mx=max(mx,(ll)abs(a[n]-a[n-1]));
else{
if (a[i]>a[i-1]&&a[i]>a[i+1])mx=max(mx,2*(a[i]-max(a[i-1],a[i+1])));
if (a[i]<a[i-1]&&a[i]<a[i+1])mx=max(mx,2*(min(a[i-1],a[i+1])-a[i]));
}
}
cout<<ans-mx<<endl;
}
return 0;
}
C.Triangles
题意:
给定一个由数字组成的矩阵,问每个数字组成的三角形的面积最大分别是多少。
每个数字的答案你可以最多修改一个元素来使得当前的三角形面积最大
三角形需满足,有一条边水平或竖直。
三角形面积*2处理
题解:
对于每个三角形来说只有两种情况。
在这里只讲边是水平的情况,竖直情况同理
情况一:
水平的边由原始点组成,那么第三个点可以随意取,为了最大化,我们都取在边界上
情况二:
水平的边由修改点来组成,那就对于每一行原始点肯定要么最左要么最右,然后我们让底最大,去找最大的高就行
代码写的复杂了点,其实可以不用vector存,直接记录每一行每一列的最前面和最后面的点就行
#define max(a,b) (((a)>(b))?(a):(b))
int _;
ll n;
char s[maxn][maxn];
vector<int>v1[10][maxn],v2[10][maxn];//v1 v2分别记录行列
ll ans[10];
ll mxl[10],mnl[10],mxc[10],mnc[10];
int main() {
for(scanf("%d",&_);_;_--){
scanf("%lld"