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; }
 
 
   |