D. Weights Assignment For Tree Edges
题意: 给定一个 n n n 个结点的有根树, 给定一个长度为 n n n 数组 b b b, b i b_i bi 表示节点 i i i 的祖先是 b i b_i bi, 只有根节点的 b i = i b_i = i bi=i, 给定一个数组p -树中顶点的排列, 并且保证前一个点到根节点的距离小于后一个节点到根节点的距离
分析: 首先: 我们考虑从根节点出发, 按照距离由小到大依次计算, 然后计算过程中, 如果已经计算到了节点 i i i, 却发现父节点的答案还未算出来, 显然无解, 如果 p [ 1 ] p[1] p[1] 不是根节点, 显然无解, 根节点到自身的距离为 0 0 0, 一定最小
#include<bits/stdc++.h>
#define x first
#define y seoncd
#define int long long
#define gg exit(0);
#define sf1(x) scanf("%lld",&x)
#define sf2(x,y) scanf("%lld%lld",&x,&y)
#define pr1(x) printf("%lld\n", x)
#define pr2(x, y) printf("%lld%lld\n", x, y)
#define debug printf("debug\n");
const int N = 3e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int t, ans[N], fa[N], pos[N], n, root, dist[N];
vector<int>G[N];
void solve()
{
cin >> n;
for(int i = 1; i <= n; i ++ ) cin >> fa[i], G[i].clear(); //初始化图
for(int i = 1; i <= n; i ++ )
{
if(fa[i] == i)
{
root = i; //保存根节点
continue;
}
G[fa[i]].push_back(i); //因为我们是从根节点出发, 所以要从父节点向子节点连边就可以了
}
for(int i = 1; i <= n; i ++ ) cin >> pos[i]; //读入
memset(ans, -1, sizeof ans); //初始化
memset(dist, 0, sizeof dist); //初始化
int flag = 1;
ans[root] = 0; //一定要记得初始化根节点答案为0
for(int i = 1; i <= n; i ++ )
{
if(ans[fa[pos[i]]] == -1) //无解
{
flag = 0;
break;
}
if(pos[i] == root) continue;
dist[pos[i]] = dist[pos[i - 1]] + 1; //这里加上任何数都可以,只要前面的大即可
ans[pos[i]] = dist[pos[i]] - dist[fa[pos[i]]];
}
if(!flag || pos[1] != root) //无解情况
{
cout << -1 << '\n';
return;
}
for(int i = 1; i <= n; i ++ ) cout << ans[i] << " ";
cout << '\n';
}
signed main()
{
//t = 1;
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> t;
while(t -- )
solve();
}
C. Polycarp Recovers the Permutation
题意: 给定一个 n n n 的排列 p p p, 还给定了一个结果数组 a a a, 每次从 p p p 的最左端和最右端选择一个最小的插入 a a a, 如果是从最左端选出来的,那么插入 a a a 数组的左端, 如果是从最右端选出来的,那么插入 a a a 数组的右端, 并将其从 p p p 数组中删去, 现在已知了 a a a 数组, 让你求出 p p p 数组, 或者输出 − 1 -1 −1 表示无解
分析: 首先要有解, 必须最大的数 n n n 位于数组 a a a 的最左端或者最右端, 然后这里倒推就行了, 从左右两端选择最大的插入 p p p 数组, 因为要涉及头插尾插, 头删尾删, 所以我们可以利用一下双端队列 d e q u e deque deque
#include<bits/stdc++.h>
#define x first
#define y seoncd
#define int long long
#define gg exit(0);
#define sf1(x) scanf("%lld",&x)
#define sf2(x,y) scanf("%lld%lld",&x,&y)
#define pr1(x) printf("%lld\n", x)
#define pr2(x, y) printf("%lld%lld\n", x, y)
#define debug printf("debug\n");
const int N = 3e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int t, n, a[N], m;
void solve()
{
cin >> n;
deque<int>s1;
for(int i = 1; i <= n; i ++ ) cin >> a[i], s1.push_back(a[i]); //插入双端队列
if(n != a[n] && n != a[1]) //判断无解情况
{
cout << -1 << '\n';
return;
}
else
{
deque<int>s2;
while(!s1.empty()) //当还未被全部取出
{
int num1 = s1.front(), num2 = s1.back(); //取出最左端和最右端的元素
if(num1 > num2) s2.push_front(num1), s1.pop_front(); //选择最大的插入
else s2.push_back(num2), s1.pop_back();
}
for(auto x : s2) cout << x << " "; //输出结果
cout << '\n';
}
}
signed main()
{
//t = 1;
scanf("%lld", &t);
while(t -- )
solve();
}
B. Team Composition: Programmers and Mathematicians
题意: 给定 a a a 个程序员和 b b b 个数学家, 一个团队由四个人组成, 每个团队最少 1 1 1 个程序员, 1 1 1 个数学家, 求最大团队数量
分析: 首先不难想到 ( a + b ) / 4 (a + b) / 4 (a+b)/4, 但是当 a a a 的人数不足 b b b 的三分之一时, 就只能取 a , b a,b a,b 的最小值了
#include<bits/stdc++.h>
#define x first
#define y seoncd
#define int long long
#define gg exit(0);
#define sf1(x) scanf("%lld",&x)
#define sf2(x,y) scanf("%lld%lld",&x,&y)
#define pr1(x) printf("%lld\n", x)
#define pr2(x, y) printf("%lld%lld\n", x, y)
#define debug printf("debug\n");
const int N = 1e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int t, n, a[N], m;
void solve()
{
sf2(n, m);
int minv = min(n , m), maxv = max(n, m);
if(3 * minv < maxv ) //不足三分之一
{
cout << min(minv, maxv) << '\n';
return;
}
else cout << (n + m ) / 4 << '\n';
}
signed main()
{
//t = 1;
scanf("%lld", &t);
while(t -- )
solve();
}
题意:输入一个数 n n n,每次操作可以翻转 n n n 的前 l l l 位,问最少要进行多少次操作才能使 n n n 变成偶数
分析: 如果本身就是偶数, 返回 0 0 0, 如果最高位是偶数返回 1 1 1, 如果最高位是奇数, 并且每一位中存在偶数返回 2 2 2, 否则返回 − 1 -1 −1
#include<bits/stdc++.h>
#define x first
#define y seoncd
#define int long long
#define gg exit(0);
#define sf1(x) scanf("%lld",&x)
#define sf2(x,y) scanf("%lld%lld",&x,&y)
#define pr1(x) printf("%lld\n", x)
#define pr2(x, y) printf("%lld%lld\n", x, y)
#define debug printf("debug\n");
const int N = 1e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int t, n, a[N];
void solve()
{
sf1(n);
int even = 0;
if(n % 2 == 0 )
{
cout << 0 << '\n';
return;
}
else
{
int t;
while(n)
{
t = n % 10;
if(t % 2 == 0) even ++;
n /= 10;
}
if(t % 2 == 0 ) //最高位
{
cout << 1 << '\n';
return;
}
else if(even >= 1) //有偶数
{
cout << 2 << '\n';
return;
}
else cout << -1 << '\n';
}
}
signed main()
{
//t = 1;
scanf("%lld", &t);
while(t -- )
solve();
}