题解:AT_abc379_c [ABC379C] Sowing Stones

比较简单,但细节较多,吃了不少罚时。

思路简单来说可以想象成一个有棋子的格子到下一个有棋子之间的格子全部填充,花费次数是一个首项是 11,公差是 11,末项是长度 1-1 的等差数列的和。

然后把多余的扔到下一个有棋子的格子处理。

处理边界就行了,等差数列的值是 m2m^2 级别的,要开 long long


丰富注释版代码

#include<bits/stdc++.h>
using namespace std;
long long n, m, sum, ans, flag;//flag 判无解
struct node{
	long long a, b;
}x[200005];
bool cmp(node x, node y){
	return x.a < y.a;
}
int main(){
	cin >> n >> m;
	for(long long i = 1; i <= m; i ++) cin >> x[i].a;
	for(long long i = 1; i <= m; i ++) cin >> x[i].b, sum += x[i].b;
	if(sum != n) flag = 1;//数量不合适
	sort(x + 1, x + m + 1, cmp);//按位置排序
	for(long long i = 1; i < m; i ++){
		if(x[i + 1].a - x[i].a > x[i].b) flag = 1;//不够放满
		ans += (x[i + 1].a - x[i].a) * (x[i + 1].a - x[i].a - 1) / 2LL;//上面的等差数列
		ans += (x[i].b - 1 - (x[i + 1].a - x[i].a - 1)) * (x[i + 1].a - x[i].a);//扔到下一次处理
		x[i + 1].b += (x[i].b - 1 - (x[i + 1].a - x[i].a - 1));//下一次获得到的棋子
	}
	if(x[1].a != 1) flag = 1;//第一个地方没有
	if(!flag) cout << ans + (x[m].b - 1) * x[m].b / 2LL;//最后面还有一个等差数列
	else cout << -1;
	return 0;
}

纯净版代码

#include<bits/stdc++.h>
using namespace std;
long long n, m, sum, ans, flag;
struct node{
	long long a, b;
}x[200005];
bool cmp(node x, node y){
	return x.a < y.a;
}
int main(){
	cin >> n >> m;
	for(long long i = 1; i <= m; i ++) cin >> x[i].a;
	for(long long i = 1; i <= m; i ++) cin >> x[i].b, sum += x[i].b;
	if(sum != n) flag = 1;
	sort(x + 1, x + m + 1, cmp);
	for(long long i = 1; i < m; i ++){
		if(x[i + 1].a - x[i].a > x[i].b) flag = 1;
		ans += (x[i + 1].a - x[i].a) * (x[i + 1].a - x[i].a - 1) / 2LL;
		ans += (x[i].b - 1 - (x[i + 1].a - x[i].a - 1)) * (x[i + 1].a - x[i].a);
		x[i + 1].b += (x[i].b - 1 - (x[i + 1].a - x[i].a - 1));
	}
	if(x[1].a != 1) flag = 1;
	if(!flag) cout << ans + (x[m].b - 1) * x[m].b / 2LL;
	else cout << -1;
	return 0;
}

posted on 2024-11-10 10:36  zhangzirui66  阅读(9)  评论(0)    收藏  举报  来源

导航