列表

详情


NC21470. [NOIP2018]龙虎斗

描述

轩轩和开开正在玩一款叫《龙虎斗》的游戏,游戏的棋盘是一条线段,线段上有n个兵营(自左至右编号1~n),相邻编号的兵营之间相隔1厘米,即棋盘为长度为n-1厘米的线段。i号兵营里有ci位工兵。
下面图1为n = 6的示例:

轩轩在左侧,代表“龙”;凯凯在右侧,代表“虎”。 他们以 m 号兵营作为分界, 靠左的工兵属于龙势力,靠右的工兵属于虎势力,而第 𝐦 号兵营中的工兵很纠结,他 们不属于任何一方。

一个兵营的气势为:该兵营中的工兵数 × 该兵营到 m 号兵营的距离;参与游戏 一方的势力定义为:属于这一方所有兵营的气势之和。

下面图 2 为 n = 6, m = 4 的示例,其中红色为龙方,黄色为虎方:


游戏过程中,某一刻天降神兵,共有 s1 位工兵突然出现在了p1号兵营。作为轩轩和凯凯的朋友,你知道如果龙虎双方气势差距太悬殊,轩轩和凯凯就不愿意继续玩下去了。为了让游戏继续,你需要选择一个兵营 p2,并将你手里的 s2位工兵全部派往 兵营p2,使得双方气势差距尽可能小。
注意:你手中的工兵落在哪个兵营,就和该兵营中其他工兵有相同的势力归属(如果落在 m 号兵营,则不属于任何势力)。

输入描述

输入文件的第一行包含一个正整数 n,代表兵营的数量。
接下来的一行包含 n 个正整数,相邻两数之间以一个空格分隔,第 i 个正整数代表编号为 i 的兵营中起始时的工兵数量 ci。接下来的一行包含四个正整数,相邻两数间以一个空格分隔,分别代表 m, p1, s1, s2

输出描述

输出文件有一行,包含一个正整数,即 p2,表示你选择的兵营编号。如果存在多个编号同时满足最优,取最小的编号。


示例1

输入:

6 
2 3 2 3 2 3
4 6 5 2

输出:

2

说明:

见问题描述中的图 2。
双方以 m=4 号兵营分界,有 S1 =5 位工兵突然出现在 P1 =6 号兵营。 
龙方的气势为:
2 × (4 − 1) + 3 × (4 − 2) + 2 × (4 − 3) = 14
虎方的气势为:
当你将手中的 𝑠2 = 2 位工兵派往 P2 = 2 号兵营时,龙方的气势变为:
2 × (5 − 4) + (3 + 5) × (6 − 4) = 18 14 + 2 × (4 − 2) = 18
此时双方气势相等。

示例2

输入:

6
1 1 1 1 1 16
5 4 1 1

输出:

1

说明:

双方以 𝑚=5 号兵营分界,有 𝑠1 =1 位工兵突然出现在 P1 =4 号兵营。 龙方的气势为:
1 × (5 − 1) + 1 × (5 − 2) + 1 × (5 − 3) + (1 + 1) × (5 − 4) = 11
虎方的气势为:
16 × (6 − 5) = 16
当你将手中的 S2 = 1 位工兵派往 P2 = 1 号兵营时,龙方的气势变为:
11 + 1 × (5 − 1) = 15
此时可以使双方气势的差距最小。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 27ms, 内存消耗: 2212K, 提交时间: 2019-10-27 14:38:33

#include<bits/stdc++.h>
using namespace std;
long long n,c[10000001],m,p1,s1,s2,x,a,s=0x7fffffff;
int main(){
	int i;
	cin>>n;
	for(i=1;i<=n;i++)
		scanf("%d",&c[i]);
	cin>>m>>p1>>s1>>s2;
	c[p1]+=s1;
	for(i=1;i<=n;i++)
		x+=(i-m)*c[i];
	for(i=1;i<=n;i++){
		if(labs(x+(i-m)*s2)<s){
			s=labs(x+(i-m)*s2);
			a=i;
		}
	}
	cout<<a;
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 37ms, 内存消耗: 2208K, 提交时间: 2020-10-07 12:58:37

#include<iostream>
using namespace std;
int main()
{
    long long n,a[1000000],m,p1,s1,s2,sum,ans;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	cin>>m>>p1>>s1>>s2;
	for(int i=1;i<=n;i++) sum+=a[i]*(m-i);
	sum+=s1*(m-p1);
	ans=m+int(sum*1.0/s2+0.5*(sum>0?1:-1)); 
	if(ans>n) ans=n;	
	if(ans<1) ans=1;
	cout<<ans;
	return 0;
}

Pascal(fpc 3.0.2) 解法, 执行用时: 29ms, 内存消耗: 2056K, 提交时间: 2019-11-15 16:40:31

var
a:array[1..1000000] of int64;
i:longint;
s1,s2,n,m,p1,p2,z:int64;
begin
read(n);
for i:=1 to n do
 read(a[i]);
read(m,p1,s1,s2);
inc(a[p1],s1);
for i:=1 to n do
 z:=z+a[i]*(m-i);
p2:=1;
for i:=2 to n do
 if abs(z+s2*(m-i))<abs(z+s2*(m-p2)) then p2:=i;
writeln(p2);
end.

上一题