目录
目录
涵盖知识点:思维、贪心。
比赛链接:传送门
A - Filling Diamonds
题意: (n)个菱形有多少种方法可以拼成一个钻石?
题解: 最终所成图形中只有一个菱形可以立着。所以只有(n)中拼法。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--) {
int n;
cin >> n;
cout << n << "
";
}
return 0;
}
B - Sorted Adjacent Differences
题意: 排序数组使得相邻之差的绝对值非递减。
题解: 从小到大排序后从中间开始一左一右。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int main(){
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
sort(a,a+n);
int mid=(n-1)/2;
cout<<a[mid]<<" ";
for(int i=1;i<=mid+1;i++){
if(mid+i<n)cout<<a[mid+i]<<" ";
if(mid-i>=0)cout<<a[mid-i]<<" ";
}
cout<<"
";
}
return 0;
}
C - Powered Addition
题意: 第(x)秒可以使任意个任意数字增加(2^{x-1}),问最少几秒使得数列非递减。
题解: 由于二进制特性我们可以讲一个数字增大到任意比他大的值。所以我们只需要找到最大的所需增加值即可。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int inf=1e9+7;
int main(){
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
int mx=-inf,res=0;
for(int i=1,a;i<=n;i++){
cin>>a;
res=max(mx-a,res);
mx=max(a,mx);
}
if(res==0)cout<<"0
";
else cout<<(int)log2(res)+1<<"
";
}
return 0;
}
D - Edge Weight Assignment
题意: 给(n)节点的数的边赋正值权,使得任意两个叶节点路径上的异或值为(0)。求最少和最多赋值种类(即不同数字的个数)
题解: 先考虑最少的情况:如果所有叶子节点距离根的奇偶性相同,那么只要一种就可以了,否则需要((1,2,3))三种,见样例。
然后考虑最多的情况。最理想的条件是每条边都填不同的数字,也就是(n-1)种(因为不用是(1)到(n-1),所以一定有解,强行构造就行了),但是考虑到一个节点有多个子节点且都为叶子节点的时候,相邻值必须为相同,所以再减去对应重复的数量即可。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
vector<int> edg[maxn];
int ans;
int c[3], dep[maxn];
void dfs(int u, int fa){
int cnt = 0;
for (int v : edg[u]){
if (v == fa)
continue;
dep[v] = dep[u] + 1;
if (edg[v].size() == 1){
c[dep[v] & 1]++;
cnt++;
}
else
dfs(v, u);
}
if (cnt >= 2)
ans -= cnt - 1;
}
int main(){
int n;
cin>>n;
for (int i = 1,x,y; i < n; i++){
cin>>x>>y;
edg[x].push_back(y);
edg[y].push_back(x);
}
int root;
for (int i = 1; i <= n; i++) {
if (edg[i].size() > 1) {
root = i;
break;
}
}
ans = n - 1;
dfs(root, 0);
printf("%d %d
", c[0] && c[1] ? 3 : 1, ans);
return 0;
}
E - Perfect Triples
题意: 一个初始为空的无限长的序列(S)满足以下条件:
- 每次加入一个三元组((a,b,c))。
- (a,b,c)都不在(S)中。
- (aoplus boplus c=0)
- 该三元组是所有满足条件中字典序最小的。
现在要求该序列的第(n)个数字。
题解: 三元组((1,2,3))能够满足异或值为(0)。那么在四进制下,保证每一位都是(1,2,3)即可。实现起来就是把二进制两位两位地合并起来写就行了。找到规律以后实现难度应该不大。具体打表的规律看这里:传送门
Accept Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[4] = {0, 2, 3, 1};
ll B(ll a) { return (a == 1) ? 2 : f[a & 3] | B(a >> 2) << 2; }
int main(){
int t;
cin>>t;
while (t--){
ll n, A[3];
cin>>n;
ll d = 1;
for (; n >= d; d <<= 2);
d >>= 2;
A[0] = d | ((n - d) / 3);
A[1] = B(A[0]);
A[2] = A[0] ^ A[1];
cout<<A[(n - d) % 3]<<"
";
}
return 0;
}