#define pos(x, y) (((x) - 1) * n + (y)) namespace Union_set { int fa[MXXN], siz[MXXN]; voidinit(int n) { for (int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1; } intfind(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } boolmerge(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) returnfalse; if (siz[x] > siz[y]) swap(x, y); fa[fx] = fy; siz[fy] += siz[fx]; returntrue; } }
structquery { int sx, sy, tx, ty, w, id; }que[100005];
boolcmp(query a, query b) { return a.w > b.w; }
char mp[MAXN][MAXN]; int sum[MAXN][MAXN]; int mxz[MAXN][MAXN];
intget(int lx, int rx, int ly, int ry) { return sum[rx][ry] - sum[lx-1][ry] - sum[rx][ly-1] + sum[lx-1][ly-1]; }
vector <pair<int, int>> vr[MAXN];
int dx[4] = {1, -1, 0, 0}; int dy[4] = {0, 0, 1, -1};
voidLinkstart(int now) { for (auto v : vr[now]) { int p = pos(v.first, v.second); for (int i = 0; i < 4; i++) { int X = v.first + dx[i], Y = v.second + dy[i]; if (X > 0 && Y > 0 && X <= n && Y <= m) if (mxz[X][Y] >= now) Union_set::merge(p, pos(X, Y)); } } }
int ans[100005];
intmain() { // freopen("data.in", "r", stdin); // freopen("vei.out", "w", stdout); read(n, m, q); for (int i = 1; i <= n; i++) scanf("%s", mp[i] + 1); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + (mp[i][j]^48); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) if (mp[i][j] == '0') { int l = 1, r = min(i, j) + 1; int res = 1; while (l < r) { int mid = (l + r) >> 1; if (!get(i - mid + 1, i, j - mid + 1, j)) res = mid, l = mid + 1; else r = mid; } mxz[i][j] = res; vr[res].emplace_back(i, j); } }
int now = 0;
for (int i = 1; i <= q; i++) { int sx, sy, tx, ty, w; read(sx, sy, tx, ty, w); now = max(now, w); que[i] = {sx, sy, tx, ty, w, i}; } sort(que + 1, que + 1 + q, cmp);
Union_set :: init(n * m);
for (int i = 1; i <= q; i++) { while (now >= que[i].w) Linkstart(now--); if (mxz[que[i].sx][que[i].sy] < que[i].w || mxz[que[i].tx][que[i].ty] < que[i].w) ans[que[i].id] = false; else ans[que[i].id] = (Union_set::find(pos(que[i].sx, que[i].sy)) == Union_set::find(pos(que[i].tx, que[i].ty))); } for (int i = 1; i <= q; i++) puts(ans[i] ? "Yes" : "No");
int cnte = 1, head[MAXN]; structedge { int to, nxt, dis; }e[MAXN<<1]; voidadde(int u, int v, int w) { e[++cnte].to = v; e[cnte].dis = w; e[cnte].nxt = head[u]; head[u] = cnte; }
int fa[MAXN], siz[MAXN], dep[MAXN], son[MAXN]; int top[MAXN], dis[MAXN]; #define v (e[i].to) voiddfs1(int u, int dad) { fa[u] = dad; siz[u] = 1; dep[u] = dep[dad] + 1; for (int i = head[u]; i; i = e[i].nxt) if (v != dad) { dis[v] = dis[u] + e[i].dis; dfs1(v, u); siz[u] += siz[v]; if (siz[v] > siz[son[u]]) son[u] = v; } } voiddfs2(int u, int tup) { top[u] = tup; if (son[u]) dfs2(son[u], tup); for (int i = head[u]; i; i = e[i].nxt) if (v != fa[u] && v != son[u]) dfs2(v, v); } #undef v intLCA(int u, int v) { while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); u = fa[top[u]]; } return dep[u] < dep[v] ? u : v; }
int dwd[MAXN], cnt1, qwq[MAXN], cnt2; bool vis[MAXN]; int pos[MAXN];
voidget_path(int u, int &t, int to, int op) { dwd[++cnt1] = u; qwq[cnt1] = t; vis[u] = 1; pos[u] = cnt1; if (u == to) return; if (op) t = t - dis[u] + dis[fa[u]]; else t = t + dis[u] - dis[fa[u]]; get_path(fa[u], t, to, op); } voidgot_path(int u, int t, int to, int op) { if (u == to) return; if (op == 1) got_path(fa[u], t + (dis[u] - dis[fa[u]]), to, op); else got_path(fa[u], t + (dis[u] - dis[fa[u]]), to, op); dwd[++cnt1] = u; qwq[cnt1] = t; vis[u] = 1; pos[u] = cnt1; } voidwalk(int u, int v, int t) { for (int i = 1; i <= cnt1; i++) vis[dwd[i]] = 0; int lca = LCA(u, v), op = 0; if (dep[u] < dep[v]) { t += dis[u] + dis[v] - 2 * dis[lca]; swap(u, v); op = 1; }
cnt1 = 0; get_path(u, t, lca, op); if (op == 1) t = t - dis[v] + dis[lca]; else t = t + dis[v] - dis[lca]; got_path(v, t, lca, op);
} bool flag = 0; voidget_poth(int u, int &t, int to, int op) { // cout << u << ' ' << t << '\n'; if (flag || u == to) return; int v = fa[u], fat; if (op) fat = t - dis[u] + dis[fa[u]]; else fat = t + dis[u] - dis[fa[u]]; if (vis[u] && vis[v]) { int id = pos[u], fid = pos[v]; if ((qwq[id] - qwq[fid]) * (t - fat) > 0) { if (qwq[id] > qwq[fid]) { if (!(t < qwq[fid] || fat > qwq[id])) return flag = 1, void(); } else { if (!(t > qwq[fid] || fat < qwq[id])) return flag = 1, void(); } } else { if (qwq[id] > t && qwq[fid] < fat || t > qwq[id] && fat < qwq[fid]) return flag = 1, void(); } } t = fat; get_poth(fa[u], t, to, op); } voidgot_poth(int u, int t, int to, int op) { // cout << u << ' ' << t << '\n'; if (flag || u == to) return; int v = fa[u], fat; if (op == 1) fat = t + dis[u] - dis[fa[u]]; else fat = t - dis[u] + dis[fa[u]]; if (vis[v] && vis[u]) { int id = pos[u], fid = pos[v]; if ((qwq[id] - qwq[fid]) * (t - fat) > 0) { if (qwq[id] > qwq[fid]) { if (!(t < qwq[fid] || fat > qwq[id])) return flag = 1, void(); } else { if (!(t > qwq[fid] || fat < qwq[id])) return flag = 1, void(); } } else { if (qwq[id] > t && qwq[fid] < fat || t > qwq[id] && fat < qwq[fid]) return flag = 1, void(); } } got_poth(fa[u], fat, to, op); } boolcheck(int u, int v, int t) { int lca = LCA(u, v); int op = 0; if (dep[u] < dep[v]) { t += dis[u] + dis[v] - 2 * dis[lca]; swap(u, v); op = 1; } get_poth(u, t, lca, op); if (flag) return1; if (op) t = t - dis[v] + dis[lca]; else t = t - dis[v] + dis[lca]; got_poth(v, t, lca, op); if (flag) return1;
return0; }
intmain() { read(n, m); for (int i = 1; i < n; i++) { int u, v, w; read(u, v, w); adde(u, v, w); adde(v, u, w); } dis[1] = 0; dfs1(1, 0); dfs2(1, 1); for (int i = 1; i <= m; i++) { flag = 0; int u, v, t; read(u, v, t); walk(u, v, t); // for (int j = 1; j <= cnt1; j++) // cout << dwd[j] << ' ' << qwq[j] << '\n';
#include<bits/stdc++.h> #define INF 0x3f3f3f3f3f3f3f3f #define ll long long #define MAXN 100005 #define MXLG 26 usingnamespace std; namespace OCTANE { template <typename T> inlinevoidread(T &x) { x = 0; bool f = 0; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = 1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } if (f) x = -x; } template <typename T> inlinevoidprint(T x) { if (x < 0) putchar('-'), x = -x; if (x > 9) print(x / 10); putchar(x%10 + '0'); } template <typename T, typename ...TT> inlinevoidread(T &x, TT &...y) { read(x); read(y...); } #define p_ putchar(' '); #define pn putchar('\n'); #define print_(x) print(x), putchar(' '); #define printn(x) print(x), putchar('\n');
}usingnamespace OCTANE;
#define lowbit(x) (x & (-x))
structnode { int val, id; }a[MAXN][MXLG]; ll b[1<<25], f[1<<25];
intmain() { int n, m; read(n, m);
for (int i = 1; i <= n; i++) { for (int j = 0; j < m; j++) read(a[i][j].val), a[i][j].id = j; sort(a[i], a[i] + m, [&](node x, node y) { return x.val < y.val; });
int s = 0; for (int j = 0; j < m; j++) { f[s] += a[i][j].val - a[i][j - 1].val; s |= 1 << a[i][j].id; } }
int S = (1 << m) - 1; for (int i = 0; i < m; i++) for (int s = 1; s <= S; s++) if ((s >> i) & 1) f[s] += f[s ^ (1 << i)]; for (int i = 0; i < m; i++) read(b[1 << i]);
ll ans = INF; for (int s = 1; s <= S; s++) { if (s == lowbit(s)) continue; b[s] = b[lowbit(s)] + b[s ^ lowbit(s)]; }
for (int s = 0; s < S; s++) ans = min(ans, f[s] + b[s ^ S]);
print(ans);
return0; }
11.7
我爹 Ak 了
11.8
T1
一个长度为 n 的01串,下标 0∼n−1 。有两种操作:
A: 选择一个 x ,将序列循环左移 x 位。也就是新序列的第 (i+x)modn 位对应原序列的第 i 位。
B: 选择一个 x , 满足序列的第 x 个位置为 1 , 且第 (x+1)modn 位置不为 1 , 交换序列的第 $x $ 个位置和第 (x+1)modn 个位置的字符。
构造一个由 l 个长度为 n 的01串构成的序列 s ,使得序列中每个串恰好有 k 个 1 。且对于 0≤i<l−1 , s[i] 既可以通过一种 A 类型的操作, 也可以通过一种 B 类型的操作, 变为 s[i+1] 。
设 s 中所有 1 下标之和为 w
对于第一个操作,那么整体左移一位也就是说有一个 x 使得 wi+x×k≡wi+1modn
对于第二个操作,那么就是说 wi+1≡wi+1modn
那么 n×k≡1modn ,也就是说 k 在 modn 有逆元 x ,所以 n,k 互质
然后构造方案的话,使 s[i]的 ki,ki+1,⋯,kk+i−1 为 1 就行
T2
n 个字符串,从每个字符串里选出一个任意一个非空前缀按任意顺序组成一个新字符串。使得这个字符串最小
正解听难想的,因为 n 很小 , 长度也很小。使用机房 :: 的随机化算法,随机选取 n 个串的顺序开搜
voidadd(int x) { for (int i = x; i <= maxn; i += x) { t.add(i, 1LL*i * 1LL*i / x%mod * mu[i / x]%mod); } } ll work(int n, int m) { ll res = 0; int N = min(n, m); for (int l = 1, r; l <= N; l = r + 1) { r = min(n / (n / l), m / (m / l)); res = (res + S(1LL, (ll)(n / l)) * S(1LL, (ll)(m / l))%mod * t.query(l, r)%mod) %mod; } return res; }
ll ans[MAXN]; intmain() { t.lim = maxn; get_prime(maxn); int T; read(T); for (int i = 1; i <= T; i++) { int n, m, a; read(n, m, a) ; q[i] = { n, m, a, i }; } sort(q + 1, q + 1 + T, [&](que a, que b) { return a.a < b.a; });
int now = 1; for (int i = 1; i <= T; i++) { while (now <= q[i].a) add(now++); ans[q[i].id] = work(q[i].n, q[i].m); } for (int i = 1; i <= T; i++) print(ans[i], '\n');
给你一个只包含字符 a 和 b 的字符串 s,你需要求出最多有多少不相交的子序列 abab。
不相交的定义为:对于 s 种的每个字符,其最多处于一个子序列中。
Solution
发现 abab 可以拆成两个 ab,问题就变成了去除尽可能多的不相交的 ab 。
不能同时选的 ab 存在一个分界点 p∈[1,n],使得所有 a 的位置小于等于 p,所有 b 的位置大于等于 p。
设不能同时选的 ab 的最大值为 mx,共有 cnt 对 ab,那么答案就是 min(⌊2cnt⌋,cnt−mx)。
现在就需要使 mx 最小化,这个可以使每个 b 去匹配它前面最近的未被匹配的 a,这样可以使这一对 ab 包含的其他 ab 最少,所以用一个栈做一下括号匹配就行了。
T3
用 0 代表空树,如果一个节点没有左子树,那么认为它的左子树是空树(右子树同理)。对任意二叉树 A,0≤A 成立;对任意非空二叉树 A,A≤0 不成立,则对于非空二叉树 A,B,A≤B 当且仅当 ls(A)≤ls(B) 且 rs(B)≤rs(A)。
问有多少不同在 A 上加 m 个点的 B ,满足 A≤B。
我们只能在特定的节点放,可以一次 dfs 求出。
有 c 个互相独立的位置,放上 m 个节点,问最终形成的二叉树森林有几种。
设 f(c,m) 表示上述问题的答案。
f(c,m)=f(c+1,m−1)+f(c−1,m) ,因为
如果有一个节点挂在第 c 个位置,节点数减少 1,互相独立的位置数反而增加了 1,状态转移为 f(c+1,m−1)。
structbit { int t[MAXN*4], lim; #define lowbit(i) (i & -i) voidadd(int i, int val) { i += 3 * n; if (!i) return; for (; i <= lim; i += lowbit(i)) t[i] += val; } intquery(int i, int res = 0) { i += 3 * n; for (; i; i -= lowbit(i)) res += t[i]; return res; } }t1, t2;
int siz[MAXN], sixz, tot, rt; int dis[MAXN]; bool vis[MAXN]; ll ans;
voidget_zx(int u) { int msiz = 0; vis[u] = siz[u] = 1; for (int v : e[u]) if (!vis[v]) { get_zx(v); siz[u] += siz[v]; msiz = max(msiz, siz[v]); } msiz = max(msiz, tot - siz[u]); if(msiz <= sixz) {sixz = msiz; rt = u;} vis[u] = 0; } int top1, top2; pair <int, int> sta1[MAXN]; pair <int, int> sta2[MAXN]; voidget_dis(int u) { vis[u] = 1; sta1[++top1] = {dis[u], u}; for (int v : e[u]) if (!vis[v]) { dis[v] = dis[u] + u + 1 - v; get_dis(v); } vis[u] = 0; } voidget_ans(int u) { top2 = 0; vis[u] = 1; t1.add(-u, 1); t2.add(u, 1); for (int v : e[u]) if (!vis[v]) { top1 = 0; dis[v] = 1 - v; get_dis(v);
for(int j = 1; j <= top1; j++) { ans += t1.query(-sta1[j].first - 2*sta1[j].second); ans += t2.query(-sta1[j].first); } for(int j = 1; j <= top1; j++) { sta2[++top2] = sta1[j]; t1.add(sta1[j].first, 1); t2.add(sta1[j].first + 2 * sta1[j].second, 1); } } t1.add(-u, -1); t2.add(u, -1); for(int i = 1; i <= top2; i++) t1.add(sta2[i].first, -1); for(int i = 1; i <= top2; i++) t2.add(sta2[i].first + 2 * sta2[i].second, -1); vis[u] = 0; } voidsolve(int u) { get_ans(u); vis[u] = 1; for (int v : e[u]) if (!vis[v]) { tot = siz[v]; sixz = INF; get_zx(v); solve(rt); } } intmain() { read(n); t1.lim = 4 * n; t2.lim = 4 * n; for(int i = 1; i < n; i++) { int u, v; read(u, v); e[u].push_back(v); e[v].push_back(u); } tot = n; sixz = INF; get_zx(1); solve(rt); print(ans);