龙虎斗-题解

龙虎斗-题解

2020.04.16

读题:

(2018NOIP普及)
原题链接
由于题面太长,在这里就不呈现了。

样例:

输入:6 2 3 2 3 2 3 4 6 5 2
输出:2

输入:6 1 1 1 1 1 16 5 4 1 1
输出:1

分析:

这个题还是挺简单的,可以分为两大部分模拟:
1.输入+计算“龙”和“虎”的“势力”;2.循环比较,找到一个合适的p2+输出。
(由于n≤100000,for()逐个位置模拟一遍是没有问题的)

存“势力”这一部分很好处理(第一部分):

	for(int i=1;i<=m-1;i++){
		suml+=((m-i)*c[i]); //“龙”方从c[1]到c[m-1]
	}
	for(int i=m+1;i<=n;i++){
		sumh+=((i-m)*c[i]);  //“虎”方从c[m+1]到c[n]
	}

关键在于第二部分。

来捋一遍第二部分模拟的思路:
从1开始逐个位置进行探索直到n,若im时应给“虎”加上势力:(i-m)*s2。
代码实现:

for(int i=1;i<=n;i++){
		if(i<m){
			lo=(m-i)*s2+suml; //i
			lmin=abs(lo-sumh);  //abs()函数求绝对值,存放给lmin
		}else{
			hu=(i-m)*s2+sumh; //i>m
			lmin=abs(suml-hu);  //同上
		}
		if(lmin<min_){
			min_=lmin;  //将lmin的值存入min_中
			p2=i;  //保存位置i
		}  //因为是从1到n,所以保证了“如果存在多个编号同时满足最优,取最小的编号。”
	}

实现:

AC代码)

#include 
#include 
#include 
#include 
#include 
using namespace std;
int n,c[100005],m,p1,p2,s1,s2,suml,sumh,min_=INT_MAX;  //INT_MAX在头文件中,是int范围内的最大值
//此处有问题,具体见代码后分析
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)	cin>>c[i];
	cin>>m>>p1>>s1>>s2;
	c[p1]+=s1;  //在计算“势力”时不要忘了
	for(int i=1;i<=m-1;i++){
		suml+=((m-i)*c[i]);
	}
	for(int i=m+1;i<=n;i++){
		sumh+=((i-m)*c[i]);
	}
	for(int i=1;i<=n;i++){
		int lmin;
		if(i<m){
			int lo=(m-i)*s2+suml;
			lmin=abs(lo-sumh);
		}else{
			int hu=(i-m)*s2+sumh;
			lmin=abs(suml-hu);
		}
		if(lmin<min_){
			min_=lmin;
			p2=i;
		}
	}
	cout<<p2;
	return 0;
}

提交后,后五个点WA掉了。
Why?

调试:

原题选段:
对于 100% 的数据,
n≤10^5,
c[i],s1,s2≤10^9 。

因此可以想到,如果题目中所有的变量的值都按最大的来算,是会超出int的范围的,因此需要用long long。经计算,没有超出long long的范围。

修改选段:

//……
#define ll long long
ll n,c[100005],m,p1,p2,s1,s2,suml,sumh,min_=LONG_MAX;  //LONG_MAX含义同INT_MAX
//后面的代码中也有需要将int改为ll的地方

当然,最后的结果是:
龙虎斗-题解_第1张图片
新手的第二篇题解

你可能感兴趣的:(龙虎斗-题解)