题解(认真写的)
2026-05-16 00:35:42
发布于:福建
题目理解
棋盘是一条线段,有n个兵营(编号1~n),每个兵营有c[i]位工兵。以m号兵营为分界:
左侧(1~m-1)属于龙方
右侧(m+1~n)属于虎方
m号兵营中立
气势计算:每个兵营的气势 = 工兵数 × 到m号兵营的距离
龙方气势 = 左侧所有兵营气势之和
虎方气势 = 右侧所有兵营气势之和
事件:
天降神兵:s1位工兵出现在p1号兵营
你手中有s2位工兵,可以派往任意兵营p2
目标:选择p2,使派兵后龙虎双方气势差最小,若有多个解取编号最小
解题思路
- 计算原始气势
龙方气势(左侧兵营):
shell
l = Σ c[i] × (m - i) (i = 1 ~ m-1)
虎方气势(右侧兵营):
shell
h = Σ c[i] × (i - m) (i = m+1 ~ n)
2. 枚举p2
将s2位工兵派往p2号兵营:
若p2 < m(龙方):龙方气势增加 s2 × (m - p2)
若p2 > m(虎方):虎方气势增加 s2 × (p2 - m)
若p2 = m(中立):气势不变
计算新气势差 |nl - nh|,记录最小值及对应兵营编号。
3. 时间复杂度
计算原始气势:O(n)
枚举p2:O(n)
总时间复杂度:O(n),空间复杂度:O(n)
#include<bits/stdc++.h>
using namespace std;
long long n;
long long c[100010];//每个兵营的工兵数
long long m,p1,s1,s2;
int main(){
cin>>n;
for(long long i=1;i<=n;i++)cin>>c[i];
cin>>m>>p1>>s1>>s2;
c[p1]+=s1;//天降神兵加入p1兵营
//计算龙方和虎方的原始气势
long long l=0,h=0;
for(long long i=1;i<=m-1;i++)l+=c[i]*(m-i);//龙方:左侧兵营
for(long long i=m+1;i<=n;i++)h+=c[i]*(i-m);//虎方:右侧兵营
long long ans=n+1;//答案兵营编号,初始化为较大值
long long mn=abs(l-h);//当前最小气势差
//枚举每个兵营作为p2
for(long long i=1;i<=n;i++){
long long nl=l,nh=h;//复制当前气势
if(i<m)nl+=s2*(m-i);//派往龙方,龙方气势增加
else if(i>m)nh+=s2*(i-m);//派往虎方,虎方气势增加
//i==m时中立,气势不变
long long d=abs(nl-nh);//新气势差
if(d<mn||(d==mn&&i<ans)){//更小或相等但编号更小
mn=d;
ans=i;
}
}
cout<<ans;
return 0;
}
龙虎斗 题解(枚举版)
题目理解
棋盘是一条线段,有n个兵营(编号1~n),每个兵营有c[i]位工兵。以m号兵营为分界:
左侧(1~m-1)属于龙方
右侧(m+1~n)属于虎方
m号兵营中立
气势计算:每个兵营的气势 = 工兵数 × 到m号兵营的距离
龙方气势 = 左侧所有兵营气势之和
虎方气势 = 右侧所有兵营气势之和
事件:
天降神兵:s1位工兵出现在p1号兵营
你手中有s2位工兵,可以派往任意兵营p2
目标:选择p2,使派兵后龙虎双方气势差最小,若有多个解取编号最小
解题思路
1. 计算原始气势
龙方气势(左侧兵营):
shell
l = Σ c[i] × (m - i) (i = 1 ~ m-1)
虎方气势(右侧兵营):
shell
h = Σ c[i] × (i - m) (i = m+1 ~ n)
2. 枚举p2
将s2位工兵派往p2号兵营:
若p2 < m(龙方):龙方气势增加 s2 × (m - p2)
若p2 > m(虎方):虎方气势增加 s2 × (p2 - m)
若p2 = m(中立):气势不变
计算新气势差 |nl - nh|,记录最小值及对应兵营编号。
3. 时间复杂度
计算原始气势:O(n)
枚举p2:O(n)
总时间复杂度:O(n),空间复杂度:O(n)
代码实现
#include<bits/stdc++.h>
using namespace std;
long long n;
long long c[100010];//兵营工兵数
long long m,p1,s1,s2;
int main(){
cin>>n;
for(long long i=1;i<=n;i++)cin>>c[i];
cin>>m>>p1>>s1>>s2;
c[p1]+=s1;//天降神兵加入p1兵营
//计算龙方和虎方的气势
long long l=0,h=0;//l:龙方气势 h:虎方气势
for(long long i=1;i<=m-1;i++){//龙方兵营
l+=c[i]*(m-i);//距离 = m-i
}
for(long long i=m+1;i<=n;i++){//虎方兵营
h+=c[i]*(i-m);//距离 = i-m
}
//枚举p2,寻找使气势差最小的兵营
long long ans=m;//默认选m号兵营(中立)
long long mn=abs(l-h);//当前气势差
for(long long i=1;i<=n;i++){
long long nl=l,nh=h;//复制当前气势
if(i<m){//派往龙方
nl+=s2*(m-i);
}else if(i>m){//派往虎方
nh+=s2*(i-m);
}//i==m时中立,气势不变
long long d=abs(nl-nh);
if(d<mn){//更小的气势差
mn=d;
ans=i;
}else if(d==mn&&i<ans){//相同气势差取编号最小
ans=i;
}
}
cout<<ans;
return 0;
}
这里空空如也







有帮助,赞一个