D:题意:树上每个顶点有个权值,求最长链,满足链上gcd > 1
解:对每个质数建虚树,每个点只会拆成log个点,所以是log2的。
1 #include <bits/stdc++.h> 2 3 const int N = 200010; 4 5 struct Edge { 6 int nex, v, len; 7 }edge[N << 1], EDGE[N << 1]; int tp, TP; 8 9 int p[N], top, e[N], pos2[N], num2, ST[N << 1][20], pw[N << 2], n, ans, id[N], last[N]; 10 int vis[N]; 11 int imp[N], K, E[N], val[N], fa[N], d[N], stk[N], use[N], Time, RT, f[N]; 12 std::vector<int> v[N]; 13 14 inline void add(int x, int y) { 15 tp++; 16 edge[tp].v = y; 17 edge[tp].nex = e[x]; 18 e[x] = tp; 19 return; 20 } 21 22 inline void ADD(int x, int y) { 23 TP++; 24 EDGE[TP].v = y; 25 EDGE[TP].len = d[y] - d[x]; 26 EDGE[TP].nex = E[x]; 27 E[x] = TP; 28 return; 29 } 30 31 inline void getp(int n) { 32 for(int i = 2; i <= n; i++) { 33 if(!vis[i]) { 34 p[++top] = i; 35 last[i] = i; 36 id[i] = top; 37 } 38 for(int j = 1; j <= top && i * p[j] <= n; j++) { 39 vis[i * p[j]] = 1; 40 last[i * p[j]] = p[j]; 41 if(i % p[j] == 0) break; 42 } 43 } 44 return; 45 } 46 47 void DFS_1(int x, int f) { 48 fa[x] = f; 49 d[x] = d[f] + 1; 50 pos2[x] = ++num2; 51 ST[num2][0] = x; 52 for(int i = e[x]; i; i = edge[i].nex) { 53 int y = edge[i].v; 54 if(y == f) { 55 continue; 56 } 57 DFS_1(y, x); 58 ST[++num2][0] = x; 59 } 60 return; 61 } 62 63 inline void prework() { 64 for(int i = 2; i <= num2; i++) pw[i] = pw[i >> 1] + 1; 65 for(int j = 1; j <= pw[num2]; j++) { 66 for(int i = 1; i + (1 << j) - 1 <= num2; i++) { 67 if(d[ST[i][j - 1]] < d[ST[i + (1 << (j - 1))][j - 1]]) 68 ST[i][j] = ST[i][j - 1]; 69 else 70 ST[i][j] = ST[i + (1 << (j - 1))][j - 1]; 71 } 72 } 73 return; 74 } 75 76 inline int lca(int x, int y) { 77 x = pos2[x]; 78 y = pos2[y]; 79 if(x > y) std::swap(x, y); 80 int t = pw[y - x + 1]; 81 if(d[ST[x][t]] < d[ST[y - (1 << t) + 1][t]]) 82 return ST[x][t]; 83 else 84 return ST[y - (1 << t) + 1][t]; 85 } 86 87 inline bool cmp(const int &a, const int &b) { 88 return pos2[a] < pos2[b]; 89 } 90 91 inline void work(int x) { 92 if(use[x] != Time) { 93 use[x] = Time; 94 f[x] = 0; 95 E[x] = 0; 96 } 97 return; 98 } 99 100 inline void build_t() { 101 std::sort(imp + 1, imp + K + 1, cmp); 102 TP = top = 0; 103 work(imp[1]); 104 stk[++top] = imp[1]; 105 for(int i = 2; i <= K; i++) { 106 int x = imp[i], y = lca(x, stk[top]); 107 work(x); work(y); 108 while(top > 1 && pos2[y] <= pos2[stk[top - 1]]) { 109 ADD(stk[top - 1], stk[top]); 110 top--; 111 } 112 if(y != stk[top]) { 113 ADD(y, stk[top]); 114 stk[top] = y; 115 } 116 stk[++top] = x; 117 } 118 while(top > 1) { 119 ADD(stk[top - 1], stk[top]); 120 top--; 121 } 122 RT = stk[top]; 123 return; 124 } 125 126 void DFS(int x) { 127 int a = 0, b = 0; 128 for(int i = E[x]; i; i = EDGE[i].nex) { 129 int y = EDGE[i].v; 130 DFS(y); 131 if(EDGE[i].len > 1) continue; 132 if(f[y] > a) { 133 b = a; 134 a = f[y]; 135 } 136 else b = std::max(b, f[y]); 137 } 138 if(vis[x] == Time) { 139 ans = std::max(ans, a + b + 1); 140 f[x] = a + 1; 141 } 142 return; 143 } 144 145 int main() { 146 getp(N - 1); 147 memset(vis, 0, sizeof(vis)); 148 int tot = top, flag = 1; 149 150 scanf("%d", &n); 151 for(int i = 1; i <= n; i++) { 152 scanf("%d", &val[i]); 153 int x = val[i]; 154 if(x > 1) flag = 0; 155 while(x > 1) { 156 int y = last[x]; 157 while(x % y == 0) { 158 x /= y; 159 } 160 v[id[y]].push_back(i); 161 } 162 } 163 for(int i = 1, x, y; i < n; i++) { 164 scanf("%d%d", &x, &y); 165 add(x, y); add(y, x); 166 } 167 168 if(flag) { 169 puts("0"); 170 return 0; 171 } 172 173 DFS_1(1, 0); 174 prework(); 175 176 for(int i = 1; i <= tot; i++) { 177 K = 0; 178 ++Time; 179 for(int j = 0; j < (int)v[i].size(); j++) { 180 imp[++K] = v[i][j]; 181 vis[v[i][j]] = Time; 182 } 183 build_t(); 184 DFS(RT); 185 } 186 187 printf("%d ", ans); 188 return 0; 189 }
G:题意:给定序列,你要把它分成尽可能多的几段,每段的权值是异或和。
要求没有哪些段的权值异或和为0。输出最大段数。无解-1。
解:考虑无解,肯定是总异或和为0。否则一定存在解。
发现这个东西,其实等价于选出一些前缀,因为异或可以抵消,所以这些前缀能表示出的和这些段能表示出的是相同的。
然后就把前缀插入线性基,看能插入多少个。
看到异或就要想线性基。
1 #include <bits/stdc++.h> 2 3 const int N = 200010; 4 5 int b[32], a[N]; 6 7 inline int insert(int x) { 8 for(int i = 30; i >= 0 && x; i--) { 9 if(((x >> i) & 1) == 0) continue; 10 if(b[i]) x ^= b[i]; 11 else { 12 b[i] = x; 13 return 1; 14 } 15 } 16 return 0; 17 } 18 19 int main() { 20 21 int n; 22 scanf("%d", &n); 23 for(int i = 1; i <= n; i++) { 24 scanf("%d", &a[i]); 25 a[i] ^= a[i - 1]; 26 } 27 28 if(!a[n]) { 29 printf("-1 "); 30 return 0; 31 } 32 33 int cnt = 0; 34 for(int i = n; i >= 1; i--) { 35 cnt += insert(a[i]); 36 } 37 38 printf("%d ", cnt); 39 return 0; 40 }