A - DIY Wooden Ladder
維護兩個點的堆
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
priority_queue<int, vector<int>, greater<int>> Q;
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n;
scanf("%d", &n);
while (Q.size())
{
Q.pop();
}
// printf("...");
Q.push(0);
Q.push(0);
int ret = 0;
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
Q.push(x);
x = Q.top();
if (x != 0)
{
ret++;
}
Q.pop();
}
int r1 = Q.top();
Q.pop();
int r2 = Q.top();
Q.pop();
// printf("%d %d %d\n",r1,r2,ret);
if (r1 == 0 || r2 == 0)
{
printf("%d\n", 0);
continue;
}
printf("%d\n", min(ret, min(r1, r2) - 1));
}
}
B - Pillars
線段樹裸題
#include <cstdio>
#include <algorithm>
using namespace std;
int a[200050];
int rr[200050];
int sgt[200050 << 2];
void build(int p, int l, int r)
{
if (l == r)
{
sgt[p] = a[l];
return;
}
int m = (l + r) >> 1;
build(p << 1, l, m);
build(p << 1 | 1, m + 1, r);
sgt[p] = std::max(sgt[p << 1], sgt[p << 1 | 1]);
}
int maxx(int p, int l, int r, int L, int R)
{
if (L <= l && r <= R)
{
return sgt[p];
}
int m = (l + r) >> 1, ret = 0;
if (L <= m)
{
ret = max(ret, maxx(p << 1, l, m, L, R));
}
if (m < R)
{
ret = max(ret, maxx(p << 1 | 1, m + 1, r, L, R));
}
return ret;
}
void set(int p, int l, int r, int a, int x)
{
if (l == r)
{
sgt[p] = x;
return;
}
int m = (l + r) >> 1;
if (a <= m)
{
set(p << 1, l, m, a, x);
}
else
{
set(p << 1 | 1, m + 1, r, a, x);
}
sgt[p] = max(sgt[p << 1], sgt[p << 1 | 1]);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
rr[a[i]] = i;
}
build(1, 1, n);
a[rr[n]] = 0;
set(1, 1, n, rr[n], 0);
for (int i = n - 1; i >= 1; i--)
{
set(1, 1, n, rr[i], 0);
int l = rr[i], r = rr[n];
if (l > r)
{
swap(l, r);
}
if (maxx(1, 1, n, l, r) != 0)
{
puts("NO");
return 0;
}
}
puts("YES");
}
C - Array Splitting
要注意到是有序的
#include <cstdio>
#include <functional>
#include <algorithm>
using namespace std;
long long a[500000], b[500000];
int main()
{
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
b[i] = a[i] - a[i - 1];
}
sort(b + 2, b + 1 + n, greater<long long>());
long long ret = a[n] - a[1];
for (int i = 2; i <= k; i++)
{
ret -= b[i];
}
printf("%lld\n", ret);
}
D - Yet Another Subarray Problem
記得初始化就能過了
#include <cstdio>
#include <algorithm>
using namespace std;
long long a[300005], k, dp[300005][12];
int main()
{
int n, m;
scanf("%d%d%lld", &n, &m, &k);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
}
long long ret = 0;
for (int i = 1; i <= n; i++)
{
dp[i][0] = max(0ll, dp[i - 1][m - 1]) + a[i] - k;
// if(dp[i][0] < 0) {
// dp[i][0] = max(a[i]-k,0ll);
// }
if (i != 1)
{
for (int j = 1; j < m; j++)
{
dp[i][j] = a[i] + dp[i - 1][j - 1];
// if(dp[i][j] < 0) {
// dp[i][j] = 0;
// }
ret = max(dp[i][j], ret);
}
}
else
{
for (int j = 1; j < m; j++)
{
dp[i][j] = -1ll << 60;
// if(dp[i][j] < 0) {
// dp[i][j] = 0;
// }
ret = max(dp[i][j], ret);
}
}
ret = max(dp[i][0], ret);
}
printf("%lld\n", ret);
}
E - Culture Code
線段樹維護區間信息
#include <cstdio>
#include <algorithm>
using namespace std;
struct wa
{
int in, out;
} x[200050];
const int mod = 1e9 + 7;
int dp[200050 << 2], sum[200050 << 2];
void pushup(int p)
{
if (dp[p << 1] < dp[p << 1 | 1])
{
dp[p] = dp[p << 1];
sum[p] = sum[p << 1];
}
else if (dp[p << 1] > dp[p << 1 | 1])
{
dp[p] = dp[p << 1 | 1];
sum[p] = sum[p << 1 | 1];
}
else
{
dp[p] = dp[p << 1];
sum[p] = sum[p << 1] + sum[p << 1 | 1];
if (sum[p] >= mod)
sum[p] -= mod;
}
}
void build(int p, int l, int r)
{
if (l == r)
{
dp[p] = 0x3f3f3f3f;
sum[p] = 0;
// dp[p]=x[l].in;
// sum[p]=1;
return;
}
int m = (l + r) >> 1;
build(p << 1, l, m);
build(p << 1 | 1, m + 1, r);
pushup(p);
}
void update(int p, int l, int r, int a, int dpp, int kk)
{
if (l == r)
{
// if(dp[p]>dpp) {
// dp[p]=dpp;
// sum[p]=kk;
// } else if (dp[p]==dpp){
// sum[p]+=kk;
// if(sum[p]>=mod) sum[p]-=mod;
// }
dp[p] = dpp;
sum[p] = kk;
return;
}
int m = (l + r) >> 1;
if (a <= m)
{
update(p << 1, l, m, a, dpp, kk);
}
else
{
update(p << 1 | 1, m + 1, r, a, dpp, kk);
}
pushup(p);
}
void query(int p, int l, int r, int outer, int &dpp, int &kk)
{
if (outer <= x[l].in)
{
if (dp[p] < dpp)
{
dpp = dp[p];
kk = sum[p];
}
else if (dp[p] == dpp)
{
kk += sum[p];
if (kk >= mod)
kk -= mod;
}
return;
}
if (l == r)
{
return;
}
int m = (l + r) >> 1;
if (outer <= x[m].in)
{
query(p << 1, l, m, outer, dpp, kk);
query(p << 1 | 1, m + 1, r, outer, dpp, kk);
}
else
{
query(p << 1 | 1, m + 1, r, outer, dpp, kk);
}
}
bool cmp(const wa &x, const wa &y)
{
if (x.in == y.in)
{
return x.out < y.out;
}
return x.in < y.in;
}
int rm[200050];
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &x[i].out, &x[i].in);
}
sort(x + 1, x + 1 + n, cmp);
build(1, 1, n);
for (int i = n; i >= 1; i--)
{
int dpp = 0x3f3f3f3f, kk = 1;
// printf("inout %d %d\n",x[i].in,x[i].out);
query(1, 1, n, x[i].out, dpp, kk);
if (dpp != 0x3f3f3f3f)
update(1, 1, n, i, dpp + x[i].in - x[i].out, kk);
else
update(1, 1, n, i, x[i].in, 1);
// printf("%d %d %d\n", dpp ,dpp+x[i].in-x[i].out,kk);
}
printf("%d\n", sum[1]);
}
F - Coloring Game
SG函數+SG定理+矩陣快速冪
SG很好想,快速冪粘個板子,然後光速TLE。
所以還是主要看板子,trick是預處理個矩陣,此後只需要累乘到答案向量上,這樣複雜度就從降到了…
這個trick易見有好的優化:
太強大了。
#include <cstdio>
#include <vector>
#include <utility>
#include <cstring>
#include <algorithm>
using namespace std;
using namespace std;
const int MOD = 998244353;
const long long MOD2 = 1ll * MOD * MOD;
typedef vector<int> vec;
typedef vector<vec> mat;
mat operator+(const mat &a, const mat &b)
{
int n = a.size();
mat c(n, vec(n));
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
int x = a[i][j] + b[i][j];
x >= MOD ? x -= MOD : 0;
c[i][j] = x;
}
}
return c;
}
mat operator*(const mat &a, const mat &b)
{
int n = a.size();
mat c(n, vec(n));
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
long long x = 0;
for (int k = 0; k < n; ++k)
{
x += 1ll * a[i][k] * b[k][j];
x >= MOD2 ? x -= MOD2 : 0;
}
c[i][j] = x % MOD;
}
}
return c;
}
vec operator*(const mat &a, const vec &b)
{
int n = a.size();
vec c(n);
for (int i = 0; i < n; ++i)
{
long long x = 0;
for (int j = 0; j < n; ++j)
{
x += 1ll * a[i][j] * b[j];
x >= MOD2 ? x -= MOD2 : 0;
}
c[i] = x % MOD;
}
return c;
}
int len[1005];
vector<pair<int, int>> colored[1005];
int f[3][3];
mat color_matrix[3], full_matrix;
bool mex[4];
void build_matrix(int color)
{
auto &matrix = color_matrix[color];
matrix.resize(64, vec(64, 0));
for (int i = 0; i < 64; i++)
{
int s3 = (i >> 4) & 3, s2 = (i >> 2) & 3, s1 = i & 3;
memset(mex, 0, sizeof(mex));
if (f[color][0])
mex[s1] = 1;
if (f[color][1])
mex[s2] = 1;
if (f[color][2])
mex[s3] = 1;
s3 = s2, s2 = s1;
if (!mex[0])
s1 = 0;
else if (!mex[1])
s1 = 1;
else if (!mex[2])
s1 = 2;
else
s1 = 3;
int j = (s3 << 4) | (s2 << 2) | s1;
matrix[j][i]++;
}
}
mat pre[40];
long long dp[1005][5];
void init_full()
{
pre[0] = full_matrix;
for (int i = 1; i <= 30; i++)
{
pre[i] = pre[i - 1] * pre[i - 1];
}
}
void powmul(int d, vec &b)
{
for (int i = 0; i <= 30; i++)
{
if (d & 1)
b = pre[i] * b;
d >>= 1;
}
return;
}
void build_matrixs()
{
for (int i = 0; i < 3; i++)
{
build_matrix(i);
}
full_matrix = color_matrix[0] + color_matrix[1] + color_matrix[2];
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &len[i]);
}
int m;
scanf("%d", &m);
for (int i = 1; i <= m; i++)
{
int x, y, c;
scanf("%d%d%d", &x, &y, &c);
colored[x - 1].push_back({y - 1, c - 1});
}
for (int i = 0; i < n; i++)
{
sort(colored[i].begin(), colored[i].end());
}
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
scanf("%d", &f[i][j]);
}
build_matrixs();
init_full();
dp[0][0] = 1;
for (int i = 0; i < n; i++)
{
vec ret(64, 0);
ret[63] = 1;
int lst = 0;
for (auto col : colored[i])
{
powmul(col.first - lst, ret);
ret = color_matrix[col.second] * ret;
lst = col.first + 1;
}
powmul(len[i] - lst, ret);
for (int k = 0; k <= 3; k++)
for (int j = 0; j < 64; j++)
{
(dp[i + 1][k ^ (j & 3)] += (long long)dp[i][k] * ret[j] % MOD) %= MOD;
}
}
printf("%lld\n", dp[n][0]);
}