C
题意:N
N的区间。在每个区间内选出一个数字出来(左右端点可以选),使得这些数 的和为0.
先说说 我赛时的时候 为什么没做出来。
我首先就注意到 ,区间 可以分为 左右端点全是正的,和左右端点 全是 负的,还有 一正一负的情况(这种的可以取到零)。所以我就想 计算出来 取正的最大 最小值,取负的最大最小值,之后不够的 有 一正一负 来补。 我这么分类去做,破坏了顺序性。导致代码变得复杂。 没有简单的办法确定 答案数组。(当然我现在反应过来,可以开结构体,把index 存储起来,),赛时的时候觉得做不了,就没写。
正确的解法:
每个区间取最大值为sum,如果sum<0 直接输出no。
之后遍历区间,尝试将区间由原来的 右端点,变成左端点或者中间的数值。
具体的看代码,想明白就是很简单的一道题。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
int n;cin>>n;
vector<pair<int,int>>ve(n);
vector<int>a(n);
int sum=0;//计算最大值
for (int i=0;i<n;i++)
{
cin>>ve[i].first>>ve[i].second;
sum+=ve[i].second;
a[i]=ve[i].second;
}
if(sum<0){
cout<<"No\n";
return 0;
}
for (int i=0;i<n;i++)
{
//也就是说 ,这个区间取最小值
if (sum>=ve[i].second-ve[i].first)
{
sum-=(ve[i].second-ve[i].first);
a[i]=ve[i].first;
if (sum==0) break;
}
else
{
a[i]=ve[i].second-sum;sum=0;
break;
}
//这个区间取中间值
}
if (sum==0)
{
cout<<"Yes\n";
for (int i=0;i<n;i++)
cout<<a[i]<<" ";
}
else cout<<"No\n";
return 0;
}