思路
表面上看是lca的题,但实际上是一个简单的树的基础问题
对于一个结点x,树上所有点与其的lca只有两种情况,第一种是它本身和它的子树内的点与其lca是它自己,其他所有点的lca都在其祖先结点上,我们只需要递归处理x的祖先结点的值即可。算在每个结点的答案是(sz【fa】 - sz【x】) * fa 也就是祖先结点子树
题目要求输出后缀0,这样我们要维护的答案就变了,我们需要统计答案中2 和 5 的次数,后缀0的个数是两个数的较小值
代码实现
#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5 + 10, mod = 1e9 + 7, INF = 1e9;
int n, m;
int h[N], e[N], ne[N], idx;
int fa[N], sz[N];
void add (int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int dfs (int u, int father)
{
int s = 1;
for (int i = h[u]; ~i ; i = ne[i])
{
int j = e[i];
if (j == father) continue;
fa[j] = u;
s += dfs (j, u);
}
sz[u] = s;
return s;
}
int query (int x)
{
int t = x;
int cnt1 = 0, cnt2 = 0;
while(t % 2 == 0)
cnt1 ++ ,t /= 2;
t = x;
while(t % 5 == 0)
cnt2 ++ ,t /= 5;
int res1 = sz[x] * (cnt1), res2 = sz[x] * (cnt2);
int f = fa[x];
while (f != 0)
{
t = f;
cnt1 = 0, cnt2 = 0;
while(t % 2 == 0)
cnt1 ++ ,t /= 2;
t = f;
while(t % 5 == 0)
cnt2 ++ ,t /= 5;
res1 += (sz[f] - sz[x]) * cnt1 , res2 += (sz[f] - sz[x]) * cnt2;
x = f;
f = fa[f];
}
return min(res1 , res2);
}
signed main()
{
ios::sync_with_stdio (0);
cin.tie (0);
cin >> n >> m;
memset (h, -1, sizeof h);
for (int i = 0; i < n - 1; i ++)
{
int a, b;
cin >> a >> b;
add (a, b);
add (b, a);
}
dfs (1, -1);
while (m --)
{
int x;
cin >> x;
cout << query (x) << endl;
}
}
思路
对于每个人来说,他得到的冰红茶只有三种情况
Ai , 0 ,-Ai 如果一个人在p - 1 人之后复读,他就有可能会得到负收益,这是每个人都不能接受的,也就是每个人都会尽力避免负收益,最好情况就是只有不到p个人参加复读,而在不到p人复读的情况下,每个人肯定是能复读就复读,考虑到p可能小于n,所有总结就是只有n%p个人得到冰红茶
代码实现
int n , p;
cin >> n >> p;
for(int i = 0 ; i < n ; i ++)
for(int j = 0 ; j < n ; j ++)
cin >> a[i][j];
for(int i = 0 ; i < n ; i ++)
{
if(i < n % p) cout << a[i][i] << ' ';
else cout << 0 << ' ';
}
思路
考虑让所有元素相等就想到差分,只要差分数组全为0即达到目的,本题差分跟原本差分不同,b【i】 = a【i】- a【i-1】 + 3 % 3
不难发现差分数组中有1的地方才能实现操作,对于每两个相邻位置(x , y)有y = 1 时才会对x有影响
(0 , 1) 可以变成( 1 , 0 ) (1 , 1 ) 可以变成(2 , 0) (2 , 1)可以变成(0 , 0)
也就是说1 的位置可以在有0的地方随意移动, 1可以变成2,2 和 1可以抵消
所以只需1的个数大于等于2的个数即可
注意这是一个循环的差分数组,即b【1】 = a【1】 - a【n】
代码实现
#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7, INF = 1e9;
int a[N];
int b[N];
void solve()
{
int n;
cin >> n;
for (int i = 1 ; i <= n ; i ++)
cin >> a[i];
a[0] = a[n];
for (int i = 1 ; i <= n ; i ++)
b[i] = ( (a[i] - a[i - 1]) + 3) % 3;
int cnt1 = 0, cnt2 = 0;
for (int i = 1 ; i <= n ; i ++)
{
if (b[i] == 1) cnt1 ++;
else if (b[i] == 2) cnt2 ++;
}
if (cnt1 >= cnt2) cout << "Yes" << endl;
else cout << "No" << endl;
}
signed main()
{
std::ios::sync_with_stdio (false);
std::cin.tie (nullptr);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}