题意:给定三条边。问:能否通过只拆解一条边构成两两相同的四条边?
思路:分为两种情况。
case1:两条边之和等于第三边时;
case2:两条边相同且第三条边为偶数。
为了方便比较可以先进行排序。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
void solve()
{
vector<ll>v(3);
for(int i=0;i<3;i++){
cin>>v[i];
}
sort(v.begin(),v.end());
//分情况
if(v[0]+v[1]==v[2]||(v[0]==v[1]&&v[2]%2==0)||(v[2]==v[1]&&v[0]%2==0)){
cout<<"YES\n";
} else {
cout<<"NO\n";
}
}
int main()
{
int t;
cin>>t;
while(t--) solve();
return 0;
}
题意:给出一组排列,再给出一个字符串。排列中的每一个数字表示对一首歌的评分,字符串中的’0’表示不喜欢对应下标的歌曲,'1’表示喜欢对应下标的歌曲。要求对歌曲重新打分,所有喜欢歌曲的评分要高于不喜欢的歌曲且∑|重打分数−原分数|
最小。
思路:串中为1的歌曲(喜欢的歌曲)的打分必须要大于不喜欢的,并且要满足∑|重打分数−原分数|
最小则必须原来打分高的现在打分也要相对高。可以确立两种优先级1,喜欢不喜欢 2,原打分相对高低。
依照优先级排序并赋值即可,由于赋值要赋值到原位置,所以要保存原次序。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
struct node {
int data, noi, flag;
//flag喜欢
//noi原顺序
};
void solve()
{
int n;
string s;
cin >> n;
vector<node>v(n + 1);
vector<int>b(n + 1);
for (int i = 1; i <= n; i++) {
cin >> v[i].data;
v[i].noi = i;
}
cin >> s;
for (int i = 0; s[i]; i++) {
if (s[i] == '1') v[i + 1].flag = 1;//标记是否喜欢
}
sort(v.begin() + 1, v.end(), [](const node& t1, const node& t2) {
if (t1.flag != t2.flag)
return t1.flag < t2.flag;
else
return t1.data < t2.data;
});
//按优先级向原位置赋值
for (int i = n; i >= 1; i--) {
b[v[i].noi] = i;
}
for (int i = 1; i <= n; i++) {
cout << b[i] << ' ';
}
cout << endl;
}
int main()
{
int t;
cin >> t;
while (t--) solve();
return 0;
}
题意:给出序列长度n,以及限定值k。
允许两种操作:
op1:任选两个数字将两个数字变为相同的(变为两个中的任一均可)。
op2:任选数字自减。
问:至少多少次操作可以使序列元素之和不大于k。
思路:注意最优解是op1和op2的组合求出的,根据贪心思想op1一定是对最小值操作,op2一定是对较大值和最小值操作且变为最小值。
那么,令k = sum-k
k赋值为要想满足题意原序列需要减去的值。设x
表示x个较大元素执行了op2,设y
为最小值需要需要减去的部分(即最小值执行了y次op1),s[x]
为前x个元素前缀和。
则存在如下关系时满足题意,即消耗部分大于等于需要消耗部分。
k <= y + s[x] - x*(a[n]-y)
等价变换后可得到y的表达式,注意y必须向上取整。由于x是有取值范围的(最多将非最小值的所有值变为最小值即n-1步),所以最后的解是可枚举求出的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
void solve()
{
ll n,k,sum=0;
cin>>n>>k;
vector<ll>a(n+1),s(n+1,0);
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i]; //总和
}
if(k>=sum) {
cout<<0<<endl;
return;
}
sort(a.begin()+1,a.end(),greater<ll>());
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i];
}
k = sum-k;//要想满足题意原序列需要减去的值
//推公式 设x为使x个最大元素变为a[n] 设y为最小值需要需要减去的部分
//k <= y + s[x] - x*(a[n]-y)
ll ans = k;
for(int x=1;x<=n-1;x++){
ll y = max(0ll,(k-s[x]+x*a[n]+x)/(x+1));
ans = min(ans,x+y);
}
cout<<ans<<endl;
}
int main()
{
int t;
cin>>t;
while(t--) solve();
return 0;
}