题解分享
题解分享简介
拔河(编程题) - 题解
原本视频里面的代码已经被hack,因为不小心敲错了一个前缀和,下面是更正后的代码,数据两个代码都能通过,数据运气较好,没有因为标程错误而出现问题。
```cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005;
ll a[N],pre[N],ans=LLONG_MAX;
multiset<ll> s;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],pre[i]=pre[i-1]+a[i];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) s.insert(pre[j]-pre[i-1]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
ll val = pre[i-1]-pre[j-1];
auto it = s.lower_bound(val);
if(it!=s.end()) ans=min(ans,abs(*it-val));
if(it!=s.begin())
{
--it;
ans=min(ans,abs(*it-val));
}
}
for(int j=i;j<=n;j++) s.erase(s.find(pre[j]-pre[i-1]));
}
cout<<ans;
}
```
查看全文
0
0
4
1
拔河(编程题) - 题解
不一定所有人都被选上
遍历所有的左子数组,然后对右子数组二分查找邻近值。
```
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
multiset<ll> s;
int main()
{
int n;
cin>>n;
int a[n+1];
ll sum[n+1] = {0};
for(int i = 1;i<=n;i++)
{
cin>>a[i];
sum[i] = sum[i-1] + a[i]; //构造前缀和
}
for(int i = 1;i<=n;i++)
{
for(int j = i;j<=n;j++)
{
s.insert(sum[j] - sum[i-1]); //将所有的区间和存起来
}
}
ll res = LLONG_MAX;
for(int i = 1;i<n;i++) //遍历左子数组的右端点
{
for(int j = i;j<=n;j++) //删除所有与右子数组相交的区间
{
s.erase(s.find(sum[j] - sum[i-1]));
}
for(int j = 1;j<=i;j++). //遍历左子数组的左端点,根据左右端点得出左子数组的和,再二分查找最近的右子数组
{
ll target = sum[i] - sum[j-1];
auto it = s.lower_bound(target);
if(it != s.end()) //第一个>=target的数
res = min(res, abs(target - *it));
if(--it != s.begin()) //最后一个<target的数,因为是绝对值要考虑大于和小于
res = min(res,abs(target - *it));
}
}
cout<<res;
}
```
查看全文
0
0
0
2



