A - Prefix and Suffix
模拟。
//waz
#include <bits/stdc++.h>
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<int, int> PII;
typedef vector<int> 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;
}
char s[110], t[110];
int N;
int main()
{
gi(N);
scanf("%s", s + 1);
scanf("%s", t + 1);
for (int i = N; i; --i)
{
int flag = 1;
for (int j = 1; j <= i; ++j)
if (s[N - i + j] != t[j])
flag = 0;
if (flag)
{
printf("%d\n", N + N - i);
return 0;
}
}
printf("%d\n", N + N);
return 0;
}
B - Median Pyramid Easy
在n和n+1处构造出两个相同的肯定会一直传递到顶。
//waz
#include <bits/stdc++.h>
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<int, int> PII;
typedef vector<int> 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 ans[200010], vis[200010];
int main()
{
int n, x;
gii(n, x);
if (n == 2)
{
if (x == 2)
{
printf("Yes\n1\n2\n3\n");
return 0;
}
puts("No");
return 0;
}
int round = n;
n <<= 1;
--n;
int A = n - x, B = x - 1;
if (B >= 1 && A >= 2)
{
ans[round] = x;
ans[round + 1] = x - 1;
ans[round - 1] = x + 1;
ans[round + 2] = x + 2;
vis[x] = vis[x + 1] = vis[x - 1] = vis[x + 2] = 1;
int t = 0;
for (int i = 1; i <= n; ++i)
{
while (ans[t + 1]) ++t;
if (!vis[i]) ans[++t] = i;
}
puts("Yes");
for (int i = 1; i <= n; ++i)
printf("%d\n", ans[i]);
return 0;
}
else if (B >= 2 && A >= 1)
{
ans[round] = x;
ans[round + 1] = x + 1;
ans[round - 1] = x - 1;
ans[round + 2] = x - 2;
vis[x] = vis[x + 1] = vis[x - 1] = vis[x - 2] = 1;
int t = 0;
for (int i = 1; i <= n; ++i)
{
while (ans[t + 1]) ++t;
if (!vis[i]) ans[++t] = i;
}
puts("Yes");
for (int i = 1; i <= n; ++i)
printf("%d\n", ans[i]);
return 0;
}
puts("No");
return 0;
}
C - Rabbit Exercise
跳一次就相当于差分数组两个位置交换一下,这是个排列的置换,可以快速幂优化。
//waz
#include <bits/stdc++.h>
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<int, int> PII;
typedef vector<int> 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 = 100010;
void mul(int *a, int *b, int n)
{
static int t[N], h[N];
for (int i = 1; i <= n; ++i) t[i] = a[i], h[i] = b[i];
for (int i = 1; i <= n; ++i) a[i] = t[h[i]];
}
void fpow(int *a, int n, long long k)
{
static int t[N];
for (int i = 1; i <= n; ++i) t[i] = i;
for (; k; k >>= 1)
{
if (k & 1) mul(t, a, n);
mul(a, a, n);
}
for (int i = 1; i <= n; ++i) a[i] = t[i];
}
int n;
long long x[N];
int m, a[N];
long long k;
int main()
{
gi(n);
for (int i = 1; i <= n; ++i) gi(x[i]), a[i] = i;
for (int i = n; i; --i) x[i] -= x[i - 1];
gi(m);
scanf("%lld", &k);
for (int i = 1; i <= m; ++i)
{
int p;
gi(p);
swap(a[p], a[p + 1]);
}
fpow(a, n, k);
for (int i = 1; i <= n; ++i)
{
//cerr << a[i] << " : " << x[a[i]] << endl;
x[a[i]] += x[a[i - 1]];
printf("%lld\n", x[a[i]]);
}
return 0;
}
D - Median Pyramid Hard
二分答案,01抵消掉,最近的连续的就是答案。
//waz
#include <bits/stdc++.h>
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<int, int> PII;
typedef vector<int> 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 = 2e5 + 10;
int n, a[N];
bool check(int mid)
{
for (int i = 1; i <= n - 1; ++i)
{
if ((a[n + i - 1] >= mid) == (a[n + i] >= mid)) return a[n + i] >= mid;
if ((a[n - i + 1] >= mid) == (a[n - i] >= mid)) return a[n - i] >= mid;
}
return a[1] >= mid;
}
int main()
{
gi(n);
for (int i = 1; i <= 2 * n - 1; ++i) gi(a[i]);
int x = 1, v = 2 * n - 1;
for (int i = 19; ~i; --i)
if (x + (1 << i) <= v && check(x + (1 << i)))
x += 1 << i;
printf("%d\n", x);
}
E - Rotate 3x3
首先一列本质就是一个数字带有正反。
算一下移动次数和翻转次数的奇偶性判断一下即可。
//waz
#include <bits/stdc++.h>
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<int, int> PII;
typedef vector<int> 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 = 1e5 + 10;;
int a[3][N], n, s[N], d[N], p[N], cnt[2], ds[2];
int tree[N];
void change(int x) { for (; x; x -= x & -x) ++tree[x]; }
int query(int x) { int v = 0; for (; x <= n; x += x & -x) v += tree[x]; return v; }
int main()
{
gi(n);
for (int j = 0; j < 3; ++j)
for (int i = 1; i <= n; ++i)
gi(a[j][i]);
for (int i = 1; i <= n; ++i)
{
if (a[0][i] == a[1][i] + 1 && a[1][i] == a[2][i] + 1) s[i] = a[0][i] / 3, d[i] = 1;
else if (a[0][i] == a[1][i] - 1 && a[1][i] == a[2][i] - 1) s[i] = a[2][i] / 3, d[i] = 0;
else return puts("No"), 0;
if ((s[i] & 1) != (i & 1)) return puts("No"), 0;
cnt[i & 1] += d[i];
}
for (int i = 1; i <= n; ++i) p[s[i]] = i;
for (int i = 1; i <= n; i += 2)
{
int now = p[i] + (query(p[i]) << 1);
ds[1] += (abs(now - i) >> 1) & 1;
change(p[i]);
}
memset(tree, 0, sizeof tree);
for (int i = 2; i <= n; i += 2)
{
int now = p[i] + (query(p[i]) << 1);
ds[0] += (abs(now - i) >> 1) & 1;
change(p[i]);
}
if ((cnt[0] & 1) != (ds[1] & 1) || (cnt[1] & 1) != (ds[0] & 1)) return puts("No"), 0;
puts("Yes");
return 0;
}
F - Blackout
本质是一个有向图问题,我们将图染成三种颜色做一下就好了。
//waz
#include <bits/stdc++.h>
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<int, int> PII;
typedef vector<int> 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 = 1e5 + 10;
int n, m;
vector<int> e1[N], e2[N];
bool vis[N];
int co[N], flag, cnt[3], s, e;
void dfs(int u)
{
vis[u] = 1;
++s;
++cnt[co[u]];
for (auto v : e1[u])
{
++e;
if (vis[v])
{
if (co[v] != (co[u] + 1) % 3)
flag = 0;
continue;
}
co[v] = (co[u] + 1) % 3;
dfs(v);
}
for (auto v : e2[u])
{
if (vis[v])
{
if (co[v] != (co[u] + 2) % 3)
flag = 0;
continue;
}
co[v] = (co[u] + 2) % 3;
dfs(v);
}
}
long long ans;
int main()
{
gii(n, m);
for (int i = 1; i <= m; ++i)
{
int u, v;
gii(u, v);
e1[u].pb(v);
e2[v].pb(u);
}
for (int i = 1; i <= n; ++i)
{
if (!vis[i])
{
e = 0;
s = 0;
flag = 1;
cnt[0] = cnt[1] = cnt[2] = 0;
dfs(i);
if (!flag)
{
ans += 1LL * s * s;
}
else if (cnt[0] && cnt[1] && cnt[2])
{
ans += 1LL * cnt[0] * cnt[1] + 1LL * cnt[1] * cnt[2] + 1LL * cnt[0] * cnt[2];
}
else ans += e;
}
}
printf("%lld\n", ans);
return 0;
}