CSP-J-2018-龙虎斗

[NOIP2018 普及组] 龙虎斗 - 洛谷


解题思路:

1.一道数据量比较大的模拟题,首先看数据范围,看到最大的数据为10的九次,那么接下来设置的所有整数变量,都设置为long long

2.接下来分析题意,要求两边的势力差的绝对值要小,势力是和编号还有每个编号的兵力决定的,那么可以设置一个结构体,来存放n个变量的id和num,输入数据

3.接下来,将p1号兵营加入人数s1,根据m的左右分别计算龙兵的势力和虎兵的势力,分别用sumA和sumB表示

4.开始判断sumA 和sumB 的大小,如果sumA大,那么肯定添加到sumB一方的编号中,那就从m+1的编号到n中依次加入s2求得虎兵的新势力,求出后再看与sumA的差的绝对值是否小于他俩原来的差,如果小的话,说明缩小差距了,那么将此时的最小值更新,并将此刻的id号存下来,注意这里要设置一个布尔变量,如果s2添加到任意一个编号中都没有原来的势力差小,那么将s2应该添加到m号兵营

5.如果sumB大的话,同理

6.如果两方相等的话,说明此时已经最小了,那么注意判断s2的人数,如果是0的话,他应该加入到1号兵营,不会对结果产生影响,而且满足编号最小,如果非0的话,加入m号兵营


#include<bits/stdc++.h>
using namespace std;
struct node{
	int id;
	long long num;
}a[1000005];
int main()
{
	int n,ans;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		a[i].id=i;
		cin>>a[i].num;
	}
	long long m,p1,s1,s2;
	cin>>m>>p1>>s1>>s2;
	a[p1].num=a[p1].num+s1;//将p1号兵营补充s1人数 
	long long sumA=0,sumB=0;
	for(int i=1;i<m;i++)
	{
		sumA=sumA+(m-a[i].id)*a[i].num;
	}//计算龙兵的势力 
	for(int i=m+1;i<=n;i++)
	{
		sumB=sumB+(a[i].id-m)*a[i].num;
	}//计算虎兵的势力 
	if(sumA>sumB)//如果龙兵的势力比较大,那么将s2填入虎兵 
	{
		long long x=sumA-sumB;//计算此时的双方差距 
		bool flag=0;
		for(int i=m+1;i<=n;i++)
		{
			long long sumC=sumB+(a[i].id-m)*s2;//如果将s2添加到此时id中 
			long long min=fabs(sumC-sumA);
			if(min<x)//计算此时虎兵的兵力和龙兵的兵力,如果差绝对值小于x 
			{
				x=min;//那么更新最小值 
				ans=a[i].id;//将id赋值给ans 
				flag=1;
			}
		}
		if(flag==0)//如果添加到虎兵的任何一个编号里都大于绝对值 
		ans=m;//添加到m号兵营里 
	}
	else if(sumA<sumB)//如果虎兵的势力比较大,那么将s2填入龙兵 
	{
		long long x=sumB-sumA;
		bool flag=0;
		for(int i=1;i<m;i++)
		{
			long long sumC=sumA+(m-a[i].id)*s2;
			long long min=fabs(sumC-sumB);
			if(min<x)
			{
				x=min;
				ans=a[i].id;
				flag=1;
			}
		}
		if(flag==0)
		ans=m;
	}
	else//如果龙兵虎兵的势力相等 
	{
		if(s2==0)//如果s2的人数为0,则应该添加到编号1处 
		ans=1;
		else//否则,添加到m号处 
		ans=m;
	}
	cout<<ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值