A. Filling Diamonds
分析一下就可以发现要你输出的是可以有多少种竖着的菱形,而且竖着的菱形只能有一个,所以可以得出结论,输入n输出n
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define INF 1ll<<60
const int maxn = 1e2+10;
int main(){
int t;
scanf("%d", &t);
for(int p = 1; p <= t; p++){
int n;
scanf("%d", &n);
printf("%d\n", n);
}
return 0;
}
B. Sorted Adjacent Differences
题意很清楚,给你一个长度为n的数组,对其重新排列,使得满足|a1−a2|≤|a2−a3|≤…≤|an−1−an|这样的等式。
思路:首先sort一遍,然后从中间开始一左一右开始选,符合前面的不等式。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define INF 1ll<<60
const int maxn = 1e5+10;
ll a[maxn];
int main(){
int t;
scanf("%d", &t);
while(t--){
int n;
scanf("%d", &n);
rep(i, 0, n){
scanf("%lld", &a[i]);
}
sort(a, a+n);
int mid = n/2;
int l = mid-1, r = mid+1;
printf("%lld ", a[mid]);
while(l!=-1 || r!=n){
if(l!=-1) printf("%lld ", a[l--]);
if(r!=n) printf("%lld ", a[r++]);
}
printf("\n");
}
return 0;
}
C. Powered Addition
想要加的是最小值,则可以这么想,minn = a[i]前的最大值-a[i], 然后在minn中取最大值,所要输出的值为minn的二进制的最高位。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define INF 1ll<<60
const int maxn = 1e5+10;
ll a[maxn];
int main(){
int t;
scanf("%d", &t);
while(t--){
int n;
scanf("%d", &n);
rep(i, 0, n){
scanf("%lld", &a[i]);
}
ll minn = 0, ma = a[0];
rep(i, 1, n){
minn = max(ma-a[i], minn);
ma = max(ma, a[i]);
}
ll ans = 0;
while(minn){
minn /= 2;
ans++;
}
printf("%lld\n", ans);
}
return 0;
}
D. Edge Weight Assignment
题意:给你一棵树,然后给每条边赋值,使得叶子节点之间经过的路径的权值异或和为零,问你赋予这些路径的权值最少可以有多少种不同的数字,最多可以有多少种不同的数字。
思路:对于最小值如果两个叶子节点之间存在经过奇数条边的最小值即为3,否则为1,对于最大值,初始值为n-1,即n-1条边,如果存在两个叶子节点公用一个结点则最大值减一,最后可得答案。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define INF 1ll<<60
const int maxn = 1e5+10;
vector<int> v[maxn];
int flag = 0;
int x;
int vis[maxn];
void dfs(int step, int ans){
if(v[step].size()==1){
if(ans%2!=0) flag = 1;
//printf("%d ", ans);
return ;
}
for(int i = 0; i < v[step].size(); i++){
if(vis[v[step][i]]==0){
vis[v[step][i]] = 1;
dfs(v[step][i], ans+1);
vis[v[step][i]] = 0;
}
}
}
int main(){
int n;
scanf("%d", &n);
rep(i, 0, n-1){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);v[y].push_back(x);
}
rep(i, 1, n+1){
if(v[i].size()==1){
x=i;
vis[i] = 1;vis[v[i][0]] = 1;
dfs(v[i][0], 1);
break;
}
}
if(flag) printf("3 ");
else printf("1 ");
int sum = 0;
rep(i, 1, n+1){
int ans = 0;
if(v[i].size()>=2)
rep(j, 0, v[i].size()){
if(v[v[i][j]].size()==1){
ans++;
}
}
if(ans>=2) sum += ans-1;
}
printf("%d\n", n-1-sum);
return 0;
}
本文深入解析了四道算法竞赛题目,包括A.FillingDiamonds的菱形填充计数,B.SortedAdjacentDifferences的排序与相邻差值优化,C.PoweredAddition的最小值加法策略,以及D.EdgeWeightAssignment的树状结构边权分配问题。通过对每道题目的详细分析和代码实现,展示了算法设计与优化的思维过程。
1613

被折叠的 条评论
为什么被折叠?



