QAQ:我太难了
A. Even But Not Even
题意:
给你一个长度为n的数组a,你可把其中一个数的值加一,这个操作你可以做无数次,要求最后的数组之和不等于零,数组之积不等于0,输出所需最小的操作数。
思路:
暴力模拟即可,要求数组中不能有0,和不等于0。
代码:
#include <bits/stdc++.h>
using namespace std;
int num[105];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
cin >> n;
int sum = 0,ans = 0;
for(int i = 0;i<n;++i)
{
cin >> num[i];
if(num[i]==0)
{
ans++;
sum+=1;
}
else
{
sum+=num[i];
}
}
if(sum!=0)
printf("%d\n",ans);
else
printf("%d\n",ans+1);
}
return 0;
}
B. Array Sharpening
题意:
给你一个数组n,n保证是个偶数,将这两个数组划分为等大小的两个数组,使这两个数组中位数之差的绝对值最小。输出这个最小值。
思路:
将数组从小到大排序,答案就是位于中间的两个数差的绝对值。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
typedef long long LL;
LL num[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
cin >> n;
n*=2;
LL sum1 = 0,sum2 = 0;
for(int i = 0;i<n;++i)
cin >>num[i];
sort(num,num+n);
cout << abs(num[n/2]-num[n/2-1]) << endl;
}
return 0;
}
C. Anu Has a Function
题意:
定义一个函数F(x,y) = (x|y)-y,给你一个函数,你可以将其重新排列,使得F(F……F(F(a1, a2),a3,……an-1),an)的值最大,输出重新排序后的数组。
思路:
首先,我们来分析下二进制下的这个函数,可以发现这个函数的结果就是先把所有x与y都是1的位变成0之后得到的数,这表示对于所有数的某一位来说,只要这一位的1的个数大于1,那么最终结果上这一位就会变成0,因此,我们需要遍历数组统计每一位是1的数的个数,然后从高位到低位遍历,找到第一个只出现1次的那一位,将提供这一位的那个数作为第一个数,剩下的数的顺序不会影响到最终结果,按照顺序输出就好。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
typedef long long LL;
LL num[maxn];
vector<LL>vec;
int d[35],mp[35];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i<=n;++i)
{
scanf("%lld",&num[i]);
for(LL j = 0;j<=31;++j)
{
if(LL(1<<j)&num[i])
{
//cout << (1<<j) <<endl;
d[j]++;
mp[j] = i;
}
}
}
int k= -1;
for(int i = 31;i>=0;--i)
{
if(d[i]==1)
{
k = mp[i];
break;
}
}
if(k!=-1)
{
cout << num[k];
for(int i = 1;i<=n;++i)
{
if(i==k)
continue;
cout << " " << num[i];
}
cout << "\n";
}
else
{
cout <<num[1];
for(int i = 2;i<=n;++i)
{
cout << " " <<num[i];
}
cout << "\n";
}
return 0;
}
D. Aerodynamic
题意:
给你n个点,这n个点能够成一个凸包P。
思路:
题目有点复杂,但是最后的结论是判断P是不是一个中心对称图形。解析可以看这个https://www.bilibili.com/video/av87962198?p=4
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long LL;
pair<LL,LL>p[maxn];
set<pair<LL,LL> > s;
int main()
{
int n;
scanf("%d",&n);
LL x=0,y=0;
for(int i = 0;i<n;++i)
{
cin >>p[i].first >> p[i].second;
x+=p[i].first;
y+=p[i].second;
s.insert(p[i]);
}
//cout <<x << " " << y <<endl;
// p[n].first = x,p[n].second= y;
bool flag = true;
for(auto it = s.begin();it!=s.end();++it)
{
LL x1 = (2*x-n*(it->first))/n;
LL y1 = (2*y-n*(it->second))/n;
//cout <<it->first << " " << it->second << " " << x1 << " " << y1 << endl;
if(s.find(make_pair(x1,y1))==s.end())
{
flag = false;
break;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
return 0;
}
E. Water Balance
题意:
给你一个数组,你可以选择一个区间,并把这个区间里的所有数替换成为这个区间的平均数,求所能得到的字典序最小的数组。
思路:
我们可以先把每一个数都当做是一个区间,用平均数去替代区间的操作可以看作是两个相邻区间的合并,因此,我们可以从左到右遍历数组,对于每一个区间,如果它的平均值比上一个区间的平均值要小,则将这两个区间合并就一定可以降低上一个区间的平均值,对于新得到的区间,也进行同样的操作,知道不能向前合并为止。得到的就是最终的结果。还有就是要注意一下输入优化。细节可以见代码。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int n,p;
double a[maxn],len[maxn],st[maxn];
int main()
{
cin >> n;
for(int i = 1;i<=n;++i)
{
int x;
cin >> x;
a[i] = 1.0*x;
}
for(int i = 1;i<=n;++i)
{
st[++p] = a[i];
len[p] =1;
while(p>1&&st[p]<st[p-1])
{
st[p-1] = (st[p]*len[p]+st[p-1]*len[p-1])/(len[p]+len[p-1]);
len[p-1]+=len[p];
--p;
}
}
for(int i = 1;i<=p;++i)
{
for(int j = 1;j<=len[i];++j)
cout << setprecision(12) << st[i] << "\n";
}
return 0;
}
来源:https://www.cnblogs.com/baihualiaoluan/p/12446144.html