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 ",ans); else printf("%d ",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 << " "; } else { cout <<num[1]; for(int i = 2;i<=n;++i) { cout << " " <<num[i]; } cout << " "; } 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 "); else printf("NO "); 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] << " "; } return 0; }