USACO - Ag - T1
内向基环树森林,既然可以自己给定排列我们对于链的答案肯定是全部都能算上的。
对于环发现只会有 $1$ 个点没有算上贡献取最小的即可。
或者使用最大生成树也可以,因为本质上一个基环树断掉一条环上的边即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #include <bits/stdc++.h> #include <bits/extc++.h> using namespace std; using namespace __gnu_cxx; using namespace __gnu_pbds;
namespace Legendgod { namespace Read {
#ifdef Fread const int Siz = (1 << 21) + 5; char *iS, *iT, buf[Siz]; #define gc() ( iS == iT ? (iT = (iS = buf) + fread(buf, 1, Siz, stdin), iS == iT ? EOF : *iS ++) : *iS ++ ) #define getchar gc #endif template <typename T> void r1(T &x) { x = 0; char c(getchar()); int f(1); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; } template <typename T, typename...Args> void r1(T &x, Args&...arg) { r1(x), r1(arg...); } #undef getchar }
using namespace Read; #define int long long const int maxn = 2e5 + 5; int n, m, head[maxn], cnt; struct Edge { int to, next, w; }edg[maxn << 1]; void add(int u,int v,int w) { edg[++ cnt] = (Edge) {v, head[u], w}, head[u] = cnt; } int vis[maxn], Siz; vector<int> lp[maxn]; int fa[maxn], d[maxn], fla(0), ans; void dfs(int p) { vis[p] = Siz; for(int i = head[p];i;i = edg[i].next) { int to = edg[i].to; if(vis[to] && vis[to] != vis[p]) continue; if(vis[to] == vis[p] && !fla) { fla = 1; int mn(edg[i].w), y = p; while(y != to) { mn = min(mn, d[y]), y = fa[y]; } ans -= mn; } else if(!vis[to]) fa[to] = p, d[to] = edg[i].w, dfs(to);
} }
signed main() { int i, j; r1(n); for(i = 1; i <= n; ++ i) { int u, w; r1(u, w); add(i, u, w); ans += w; } for(i = 1; i <= n; ++ i) if(!vis[i]) { fla = 0; ++ Siz; dfs(i); } printf("%lld\n", ans); return 0; }
}
signed main() { return Legendgod::main(), 0; }
|
USACO - Ag - T2
考虑只要相对顺序合法即可。
不妨预处理对于每个 $(a, b)$ 点对记录每个 $a$ 前面 $b$ 出现的个数,之后通过 $\tt hash$ 存储。
复杂度是 $O(26n)$ 的。
查询的时候考虑枚举每个字符的相对位置如果都合法就行。
复杂度是 $O(26^2 n)$ 的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <bits/stdc++.h> #include <bits/extc++.h> using namespace std; using namespace __gnu_cxx; using namespace __gnu_pbds;
namespace Legendgod { namespace Read {
#ifdef Fread const int Siz = (1 << 21) + 5; char *iS, *iT, buf[Siz]; #define gc() ( iS == iT ? (iT = (iS = buf) + fread(buf, 1, Siz, stdin), iS == iT ? EOF : *iS ++) : *iS ++ ) #define getchar gc #endif template <typename T> void r1(T &x) { x = 0; char c(getchar()); int f(1); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; } template <typename T, typename...Args> void r1(T &x, Args&...arg) { r1(x), r1(arg...); } #undef getchar }
using namespace Read;
const int maxn = 2e5 + 5; typedef unsigned int uint32; const int mod1 = 1e9 + 7; const int base = 13131; int n, m;
struct Node { char s[maxn]; vector<int> vc[26]; uint32 bc[26][26]; int bc1[26][26]; int n; void init() { int i, j; scanf("%s", s + 1); n = strlen(s + 1); for(i = 1; i <= n; ++ i) vc[s[i] - 'a'].push_back(i); for(i = 0; i < 18; ++ i) for(j = i + 1; j < 18; ++ j) { for(int k = 1; k <= n; ++ k) if(s[k] == (i + 'a') || s[k] == (j + 'a')) { bc[i][j] = bc[i][j] * base + s[k]; } } } }S, T;
char c[maxn]; int a[maxn];
signed main() {
int i, j; S.init(), T.init(); int Q; r1(Q); string ans; while(Q --) { scanf("%s", c + 1); int ts = strlen(c + 1); for(i = 1; i <= ts; ++ i) a[i] = c[i] - 'a'; int lf(1); sort(a + 1, a + ts + 1); for(i = 1; i <= ts && lf; ++ i) if(S.vc[a[i]].size() != T.vc[a[i]].size()) lf = 0; for(i = 1; i <= ts && lf; ++ i) for(j = i + 1; j <= ts; ++ j) { if(S.bc[a[i]][a[j]] != T.bc[a[i]][a[j]]) { lf = 0; break; } } if(lf) ans += 'Y'; else ans += 'N'; } puts(ans.c_str()); return 0; }
}
signed main() { return Legendgod::main(), 0; }
|
USACO - Ag - T3
考虑 $oc$ 可以通过变换 $o \to wc$ 变成 $w$ 然后变成 $co$,所以是有交换律的。
所以考虑最终答案只需要判断区间每种元素的个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| #include <bits/stdc++.h> #include <bits/extc++.h> using namespace std; using namespace __gnu_cxx; using namespace __gnu_pbds;
namespace Legendgod { namespace Read {
#ifdef Fread const int Siz = (1 << 21) + 5; char *iS, *iT, buf[Siz]; #define gc() ( iS == iT ? (iT = (iS = buf) + fread(buf, 1, Siz, stdin), iS == iT ? EOF : *iS ++) : *iS ++ ) #define getchar gc #endif template <typename T> void r1(T &x) { x = 0; char c(getchar()); int f(1); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; } template <typename T, typename...Args> void r1(T &x, Args&...arg) { r1(x), r1(arg...); } #undef getchar }
using namespace Read;
const int maxn = 2e5 + 5; int n, m; char s[maxn]; int a[3][maxn]; map<char, int> mp;
signed main() { int i, j; mp['C'] = 0, mp['O'] = 1, mp['W'] = 2; scanf("%s", s + 1); n = strlen(s + 1); for(i = 1; i <= n; ++ i) { a[0][i] += a[0][i - 1]; a[1][i] += a[1][i - 1]; a[2][i] += a[2][i - 1]; a[mp[s[i]]][i] ++; } int Q; r1(Q); string ans = ""; while(Q --) { int l, r; r1(l, r); int tmp[3]; tmp[0] = a[0][r] - a[0][l - 1]; tmp[1] = a[1][r] - a[1][l - 1]; tmp[2] = a[2][r] - a[2][l - 1]; tmp[0] &= 1; tmp[1] &= 1; tmp[2] &= 1;
if(!tmp[0] && tmp[1] && tmp[2]) { ans += 'Y'; continue; } if(tmp[0] && !tmp[1] && !tmp[2]) { ans += 'Y'; continue; } ans += 'N'; } puts(ans.c_str()); return 0; }
}
signed main() { return Legendgod::main(), 0; }
|