最近在刷AGC,就写一下题解。
A - BBQ Easy
sort完,每相邻两个组成一组,发现这样肯定是最优的。
//waz
#include
using namespace std;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
typedef pair PII;
typedef vector VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
int F()
{
char ch;
int x, a;
while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
if (ch == '-') ch = getchar(), a = -1;
else a = 1;
x = ch - '0';
while (ch = getchar(), ch >= '0' && ch <= '9')
x = (x << 1) + (x << 3) + ch - '0';
return a * x;
}
int n, L[210], ans;
int main()
{
gi(n);
for (int i = 1; i <= (n << 1); ++i) gi(L[i]);
sort(L + 1, L + 2 * n + 1);
for (int i = 1; i <= (n << 1); i += 2) ans += L[i];
printf("%d\n", ans);
return 0;
}
B - Mysterious Light
把光线分成很多平行四边形,所有平行四边形做法一样,只要递归下去就好了,只要某一边是另一边倍数就到达终点了,所以复杂度和gcd一样,是log的。
//waz
#include
using namespace std;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
typedef pair PII;
typedef vector VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
int F()
{
char ch;
int x, a;
while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
if (ch == '-') ch = getchar(), a = -1;
else a = 1;
x = ch - '0';
while (ch = getchar(), ch >= '0' && ch <= '9')
x = (x << 1) + (x << 3) + ch - '0';
return a * x;
}
long long ans = 0;
void work(long long x, long long y)
{
if (x < y)
{
ans += (y / x) * x * 2 - x;
if (y % x == 0)
return;
ans += x;
work(x, y % x);
}
else
{
ans += (x / y) * y * 2 - y;
if (x % y == 0)
return;
ans += y;
work(y, x % y);
}
}
int main()
{
long long N, X;
cin >> N >> X;
ans += N;
work(X, N - X);
cout << ans << endl;
}
C - Shorten Diameter
枚举根,如果是偶数,所有深度要小于等于k/2,如果是奇数,则有一个根的儿子里所有点的深度可以最大为k/2+1,其他都为k/2。
//waz
#include
using namespace std;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
typedef pair PII;
typedef vector VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
int F()
{
char ch;
int x, a;
while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
if (ch == '-') ch = getchar(), a = -1;
else a = 1;
x = ch - '0';
while (ch = getchar(), ch >= '0' && ch <= '9')
x = (x << 1) + (x << 3) + ch - '0';
return a * x;
}
const int N = 2010;
VI edge[N];
int n, k, dep[N], mxd;
void dfs(int u, int fa, int d)
{
if (k & 1) if(d > k / 2 + 1) return;
if (!(k & 1)) if (d > k / 2) return;
++dep[d];
mxd = max(mxd, d);
for (auto v : edge[u])
if (v != fa)
{
dfs(v, u, d + 1);
}
}
int main()
{
gii(n, k);
for (int i = 1; i < n; ++i)
{
int u, v;
gii(u, v);
edge[u].pb(v);
edge[v].pb(u);
}
int res = 0;
for (int root = 1; root <= n; ++root)
{
int mx = 0, s = 1;
for (auto son : edge[root])
{
mxd = 0;
dfs(son, root, 1);
if (k & 1) mx = max(mx, dep[k / 2 + 1]);
if (k & 1) s -= dep[k / 2 + 1];
for (int i = 1; i <= mxd; ++i) s += dep[i], dep[i] = 0;
}
res = max(res, s + mx);
}
printf("%d\n", n - res);
return 0;
}
D - Arrays and Palindrome
有一个结论:奇数不能超过2,否则无解,有解的话就把奇数放在两端,然后每次错1位放b就能保证他们全部相等了。
//waz
#include
using namespace std;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)((x).size()))
typedef pair PII;
typedef vector VI;
typedef long long int64;
typedef unsigned int uint;
typedef unsigned long long uint64;
#define gi(x) ((x) = F())
#define gii(x, y) (gi(x), gi(y))
#define giii(x, y, z) (gii(x, y), gi(z))
int F()
{
char ch;
int x, a;
while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
if (ch == '-') ch = getchar(), a = -1;
else a = 1;
x = ch - '0';
while (ch = getchar(), ch >= '0' && ch <= '9')
x = (x << 1) + (x << 3) + ch - '0';
return a * x;
}
int n, m, a[110];
bool comp(const int &i, const int &j)
{
return (i & 1) > (j & 1);
}
int b[110], ans;
int main()
{
gii(n, m);
int cnt = 0;
for (int i = 1; i <= m; ++i) gi(a[i]);
for (int i = 1; i <= m; ++i)
if (a[i] & 1) ++cnt;
if (cnt > 2)
{
puts("Impossible");
return 0;
}
sort(a + 1, a + m + 1, comp);
if (a[2] & 1) swap(a[2], a[m]);
for (int i = 1; i <= m; ++i)
printf("%d ", a[i]);
puts("");
if (m == 1)
{
if (a[1] - 1) printf("2\n%d %d \n", 1, a[1] - 1);
else printf("1\n%d \n", 1);
return 0;
}
if (a[1] - 1) b[++ans] = a[1] - 1;
for (int i = 2; i < m; ++i)
b[++ans] = a[i];
b[++ans] = a[m] + 1;
printf("%d\n", ans);
for (int i = 1; i <= ans; ++i)
printf("%d ", b[i]);
puts("");
return 0;
}
E - BBQ Hard
首先答案是sigma(i 我们可以令q[p[i]]=i,那么就是相邻的如果|q[i]-q[i+1]|>=k就能交换,所以相对顺序不变,也就是|i-j| //waz
#include
F - Wide Swap
//waz
#include