A. Array Balancing
题意: 交换
a
i
a_i
ai 和
b
i
b_i
bi, 使得
a
a
a,
b
b
b 序列相邻两项的差的绝对值最小,
分析 直接判断 a , b a,b a,b 序列相邻两项的差的绝对值之和与交换后的和,如果变小了,就交换,否则就不交换
#include<bits/stdc++.h>
#define x first
#define y seconde
#define int long long
#define gg exit(0);
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define db printf("debug\n");
const int N = 5e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int n, T;
int a[N], b[N];
void solve()
{
cin >> n;
for(int i = 1; i <= n ; i ++ ) cin >> a[i];
for(int i = 1; i <= n; i ++ ) cin >> b[i];
for(int i = 1; i <= n - 1; i ++ ) //判断就行
if(abs(a[i] - a[i + 1]) + abs(b[i] - b[i + 1]) > abs(a[i] - b[i + 1]) + abs(b[i] - a[i + 1]))
swap(a[i + 1],b[i + 1]);
int res = 0;
for(int i = 1; i <= n - 1; i ++ ) res += abs(a[i] - a[i + 1]) + abs(b[i] - b[i + 1]);
cout << res << '\n';
}
signed main()
{
//T = 1;
cin >> T;
while(T -- )
solve();
}
题意: 两种操作, + 1 +1 +1 和 × 2 ×2 ×2, 然后每次数字都要 m o d mod mod 32768 32768 32768, 求变成 0 0 0 的最小操作步数
分析: 不难想到, 我们可以先 加 X X X, 然后再成 2 Y 2^Y 2Y, 就可以 m o d mod mod 32768 32768 32768 为 0 0 0, 然后最优解一定在 15 15 15 以内, 因为可以直接 + 1 +1 +1, 变成偶数 然后成 2 14 2^{14} 214, 就 O K OK OK 了, 所以枚举 X ∈ [ 0 , 15 ] X ∈[0,15] X∈[0,15]
#include<bits/stdc++.h>
#define x first
#define y seconde
#define int long long
#define gg exit(0);
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define db printf("debug\n");
using namespace std;
typedef pair<int, int>PII;
int n, T, pow2[110];
void solve()
{
cin >> n;
for(int i = 1; i <= n; i ++ )
{
int x, minv = 1e9;
cin >>x;
if(x == 0) //特判0
{
cout << 0 << " ";
continue;
}
for(int j = 0; j <= 15; j ++ ) //枚举
{
int num = x + j, res = 0;
while(num % 2 == 0) num /= 2, res ++;
minv = min(minv, 15 - res + j); //15 - res 是现在离2^15还差多少个2, j是前面+1的操作数
}
cout << minv << '\n';
}
}
signed main()
{
io;
//T = 1;
// cin >> T;
// while(T -- )
solve();
}
题意: 使得所有树的高度相同, 奇数天可以给任意一棵树增加 1 1 1 的高度, 偶数天增加 2 2 2的高度, 当然也可以不增加, 求最少需要多少天
分析: 首先我们需要解决的是, 相同高度 X X X 为多少时是最优的, 我们不太清楚时, 我们先分析一下最少需要的, 首先如果一棵树达到 X X X 需要增长奇数高度时, 那么我们至少需要 1 1 1 天, 如果有 c n t cnt cnt 棵树需要增加奇数高度时, 至少需要 c n t × 2 + 1 cnt × 2 + 1 cnt×2+1 天, 因为每次增长 1 1 1 时, 是只有奇数天才能增长, 例如 有三颗树需要增长高度 1 1 1, 第一天给第一棵树增长 1 1 1, 第二天跳过, 第三天给第二棵树增长 1 1 1, 第四天跳过, 第五天给第三课树增长 1 1 1, 所以可以得出至少需要 2 × c n t − 1 2 × cnt - 1 2×cnt−1 天, 所以这个时候我们可以发现, X X X 可以决定 c n t cnt cnt 的大小, 所以 X X X 取值为 { m a x ( h [ i ] ) , m a x ( h [ i ] ) + 1 max(h[i]), max(h[i]) + 1 max(h[i]),max(h[i])+1 }, 然后将奇数天和偶数天增长的高度加在一起就是 3 3 3, 需要两天, 所以总和 s u m sum sum / / / 3 × 2 3 × 2 3×2, 然后这里 s u m sum sum / / / 3 3 3 是不一定能整除, 所以判断一下余数, 如果余 1 1 1 再多加 1 1 1 就可以, 余 2 2 2 多加 2 2 2 就可以
#include<bits/stdc++.h>
#define x first
#define y seconde
#define int long long
#define gg exit(0);
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define db printf("debug\n");
const int N = 3e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int n, T;
int a[N];
void solve()
{
cin >> n;
int maxv = 0, ans = 1e18;
for(int i = 1; i <= n; i ++ ) cin >> a[i], maxv = max(maxv, a[i]);
for(int t = maxv; t <= maxv + 1; t ++ ) //枚举他们需要到达的相同高度
{
int sum = 0, cnt1 = 0; //sum记录需要增长的高度, cnt1记录需要增长奇数高度的数量
for(int i = 1; i <= n; i ++ )
{
int d = t - a[i]; //需要增长的高度
sum += d;
if(d & 1) cnt1 ++; //增加奇数高度
}
int res = 0;
if(sum % 3 == 0)
res = max(sum / 3 * 2, cnt1 * 2 - 1);
else if(sum % 3 == 1)
res = max(sum / 3 * 2 + 1, cnt1 * 2 - 1);
else res = max(sum / 3 * 2 + 2, cnt1 * 2 - 1);
ans = min(res ,ans); //取最小
}
cout << ans << '\n';
}
signed main()
{
io;
//T = 1;
cin >> T;
while(T -- )
solve();
}