第十五周 12.6-12.12
12.6
状况百出的迎新杯。惶恐。
12.7
补个BC。
HDU 5593 ZYB's Tree
对树上每点求与其距离不超过k点数。k<=10.
一开始想的是用一个a[]存孩子中不超过k数,用另一个b[]存父亲传递过来的不超过k数。
但是这样转移不过来。因为父亲那边过来的不仅有父亲的父亲。还有父亲的其他孩子树。
所以想到换成用b[]存 父亲+所有孩子 不超过k数就可以转移了。
转移方程是 b[pos][i+1] = b[fa][i] - a[pos][i-1] + a[pos][i+1] 。
每个点的答案就是b[]求和。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int maxn = 500000 + 10; 6 typedef long long LL; 7 int cnt, headlist[maxn]; 8 int a[maxn][11], b[maxn][11]; 9 int ans[maxn]; 10 LL N, K, A, B; 11 12 struct node 13 { 14 int to,pre; 15 } edge[maxn * 2]; 16 17 void add(int from,int to) 18 { 19 cnt++; 20 edge[cnt].pre = headlist[from]; 21 edge[cnt].to = to; 22 headlist[from] = cnt; 23 } 24 25 void dfs1(int pos, int fa) 26 { 27 a[pos][0] = 1; 28 for(int i = headlist[pos]; i; i = edge[i].pre) 29 { 30 int to = edge[i].to; 31 if(to == fa) continue; 32 dfs1(to, pos); 33 a[pos][1]++; 34 for(int j = 1; j < K; j++) a[pos][j+1] += a[to][j]; 35 } 36 return; 37 } 38 39 void dfs2(int pos, int fa) 40 { 41 if(fa != 0) 42 { 43 b[pos][1]++; 44 for(int i = 1; i < K; i++) b[pos][i+1] += b[fa][i] - a[pos][i-1]; 45 } 46 for(int i = 0; i <= K; i++) b[pos][i] += a[pos][i] ,ans[pos] += b[pos][i]; 47 for(int i = headlist[pos]; i; i = edge[i].pre) 48 { 49 int to = edge[i].to; 50 if(to == fa) continue; 51 dfs2(to, pos); 52 } 53 return; 54 } 55 56 int main(void) 57 { 58 int T; 59 scanf("%d", &T); 60 while(T--) 61 { 62 scanf("%I64d %I64d %I64d %I64d", &N, &K, &A, &B); 63 cnt = 0; 64 memset(headlist, 0, sizeof(headlist)); 65 memset(a, 0, sizeof(a)); 66 memset(b, 0, sizeof(b)); 67 memset(ans, 0, sizeof(ans)); 68 for(LL i = 2; i <= N; i++) 69 { 70 LL b = (A * i + B) % (i - 1) + 1; 71 add(i, b); 72 add(b, i); 73 } 74 dfs1(1,0); 75 dfs2(1,0); 76 int ret = 0; 77 for(int i = 1; i <= N; i++) ret ^= ans[i]; 78 printf("%d\n", ret); 79 } 80 return 0; 81 }
停滞很久的AC自动姬。
HDU 2457 DNA repair
没有注意到可以有20*50*1000的做法。
偷看题解一开始还以为要在Trie图上dp。然而直接dp就可以了。
由于曾在写法上被坑过。先是很乖的写了sb法。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxnode = 1010, sigma_size = 4; 8 char str[] = "AGCT", s[1010]; 9 int N; 10 11 struct Ac_auto 12 { 13 int Next[maxnode][sigma_size]; 14 int fail[maxnode]; 15 int val[maxnode]; 16 int sz; 17 18 Ac_auto(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 19 void init(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 20 21 int idx(char c) 22 { 23 if(c == 'A') return 0; 24 else if(c == 'G') return 1; 25 else if(c == 'C') return 2; 26 return 3; 27 } 28 29 void insert(char *s) 30 { 31 int u = 0, n = strlen(s); 32 for(int i = 0; i < n; i++) 33 { 34 int c = idx(s[i]); 35 if(!Next[u][c]) 36 { 37 memset(Next[sz], 0, sizeof(Next[sz])); 38 val[sz] = 0; 39 Next[u][c] = sz++; 40 } 41 u = Next[u][c]; 42 } 43 val[u] = 1; 44 } 45 46 void build() 47 { 48 queue<int> q; 49 fail[0] = 0; 50 for(int i = 0; i < sigma_size; i++) if(Next[0][i]) 51 { 52 fail[Next[0][i]] = 0; 53 q.push(Next[0][i]); 54 } 55 while(!q.empty()) 56 { 57 int pos = q.front(); q.pop(); 58 for(int i = 0; i < sigma_size; i++) 59 { 60 if(!Next[pos][i]) Next[pos][i] = Next[fail[pos]][i]; 61 else 62 { 63 fail[Next[pos][i]] = Next[fail[pos]][i]; 64 q.push(Next[pos][i]); 65 } 66 } 67 } 68 } 69 70 }ACA; 71 72 const int INF = 100000; 73 int dp[1010][1010]; 74 int solve() 75 { 76 int len = strlen(s); 77 for(int i = 0; i <= len; i++) 78 for(int j = 0; j < ACA.sz; j++) 79 dp[i][j] = INF; 80 dp[0][0] = 0; 81 for(int i = 0; i < len; i++) 82 { 83 for(int j = 0; j < ACA.sz; j++) 84 { 85 if(dp[i][j] == INF) continue; 86 for(int k = 0; k < 4; k++) 87 { 88 int pos = ACA.Next[j][k], ok = 1; 89 while(pos) 90 { 91 if(ACA.val[pos]) {ok = 0; break;} 92 pos = ACA.fail[pos]; 93 } 94 if(!ok) continue; 95 int & t = dp[i+1][ACA.Next[j][k]]; 96 t = min(t, dp[i][j] + (str[k] != s[i]) ); 97 } 98 } 99 } 100 int ans = INF; 101 for(int i = 0; i < ACA.sz; i++) ans = min(ans, dp[len][i]); 102 return ans == INF ? -1 : ans; 103 } 104 105 int main(void) 106 { 107 int kase = 0; 108 while(~scanf("%d", &N) && N) 109 { 110 ACA.init(); 111 for(int i = 1; i <= N; i++) 112 { 113 char tmp[22]; 114 scanf("%s", tmp); 115 ACA.insert(tmp); 116 } 117 ACA.build(); 118 scanf("%s", s); 119 printf("Case %d: %d\n", ++kase, solve()); 120 } 121 return 0; 122 }
不过这次改了一下写法还是过的。也如预期快了一点点。(并不
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxnode = 1010, sigma_size = 4; 8 char str[] = "AGCT", s[1010]; 9 int N; 10 11 struct Ac_auto 12 { 13 int Next[maxnode][sigma_size]; 14 int fail[maxnode]; 15 int val[maxnode]; 16 int sz; 17 18 Ac_auto(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 19 void init(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 20 21 int idx(char c) 22 { 23 if(c == 'A') return 0; 24 else if(c == 'G') return 1; 25 else if(c == 'C') return 2; 26 return 3; 27 } 28 29 void insert(char *s) 30 { 31 int u = 0, n = strlen(s); 32 for(int i = 0; i < n; i++) 33 { 34 int c = idx(s[i]); 35 if(!Next[u][c]) 36 { 37 memset(Next[sz], 0, sizeof(Next[sz])); 38 val[sz] = 0; 39 Next[u][c] = sz++; 40 } 41 u = Next[u][c]; 42 } 43 val[u] = 1; 44 } 45 46 void build() 47 { 48 queue<int> q; 49 fail[0] = 0; 50 for(int i = 0; i < sigma_size; i++) if(Next[0][i]) 51 { 52 fail[Next[0][i]] = 0; 53 q.push(Next[0][i]); 54 } 55 while(!q.empty()) 56 { 57 int pos = q.front(); q.pop(); 58 for(int i = 0; i < sigma_size; i++) 59 { 60 if(!Next[pos][i]) Next[pos][i] = Next[fail[pos]][i]; 61 else 62 { 63 fail[Next[pos][i]] = Next[fail[pos]][i]; 64 q.push(Next[pos][i]); 65 } 66 if(val[fail[Next[pos][i]]]) val[Next[pos][i]] = 1; 67 } 68 } 69 } 70 71 }ACA; 72 73 const int INF = 100000; 74 int dp[1010][1010]; 75 int solve() 76 { 77 int len = strlen(s); 78 for(int i = 0; i <= len; i++) 79 for(int j = 0; j < ACA.sz; j++) 80 dp[i][j] = INF; 81 dp[0][0] = 0; 82 for(int i = 0; i < len; i++) 83 { 84 for(int j = 0; j < ACA.sz; j++) 85 { 86 if(dp[i][j] == INF) continue; 87 for(int k = 0; k < 4; k++) 88 { 89 if(ACA.val[ACA.Next[j][k]]) continue; 90 int & t = dp[i+1][ACA.Next[j][k]]; 91 t = min(t, dp[i][j] + (str[k] != s[i]) ); 92 } 93 } 94 } 95 int ans = INF; 96 for(int i = 0; i < ACA.sz; i++) ans = min(ans, dp[len][i]); 97 return ans == INF ? -1 : ans; 98 } 99 100 int main(void) 101 { 102 int kase = 0; 103 while(~scanf("%d", &N) && N) 104 { 105 ACA.init(); 106 for(int i = 1; i <= N; i++) 107 { 108 char tmp[22]; 109 scanf("%s", tmp); 110 ACA.insert(tmp); 111 } 112 ACA.build(); 113 scanf("%s", s); 114 printf("Case %d: %d\n", ++kase, solve()); 115 } 116 return 0; 117 }
12.8
HNU 11187 Emoticons :-)
找到一个就回原点。gets读。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxnode = 2222, sigma_size = 256; 8 int N, M; 9 10 struct Ac_auto 11 { 12 int Next[maxnode][sigma_size]; 13 int fail[maxnode]; 14 int val[maxnode]; 15 int sz; 16 17 Ac_auto(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 18 void init(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 19 20 int idx(char c){return c;} 21 22 void insert(char *s) 23 { 24 int u = 0, n = strlen(s); 25 for(int i = 0; i < n; i++) 26 { 27 int c = idx(s[i]); 28 if(!Next[u][c]) 29 { 30 memset(Next[sz], 0, sizeof(Next[sz])); 31 val[sz] = 0; 32 Next[u][c] = sz++; 33 } 34 u = Next[u][c]; 35 } 36 val[u] = 1; 37 } 38 39 void build() 40 { 41 queue<int> q; 42 fail[0] = 0; 43 for(int i = 0; i < sigma_size; i++) if(Next[0][i]) 44 { 45 fail[Next[0][i]] = 0; 46 q.push(Next[0][i]); 47 } 48 while(!q.empty()) 49 { 50 int pos = q.front(); q.pop(); 51 for(int i = 0; i < sigma_size; i++) 52 { 53 if(!Next[pos][i]) Next[pos][i] = Next[fail[pos]][i]; 54 else 55 { 56 fail[Next[pos][i]] = Next[fail[pos]][i]; 57 if(val[fail[Next[pos][i]]]) val[Next[pos][i]] = 1; 58 q.push(Next[pos][i]); 59 } 60 } 61 } 62 } 63 64 int cal(char * s) 65 { 66 int ret = 0; 67 int len = strlen(s), pos = 0; 68 for(int i = 0; i < len; i++) 69 { 70 pos = Next[pos][idx(s[i])]; 71 int tmp = pos, flag = 0; 72 while(tmp) 73 { 74 if(val[tmp]) {flag = 1; break;} 75 tmp = fail[tmp]; 76 } 77 if(flag) {pos = 0; ret++;} 78 } 79 return ret; 80 } 81 82 }ACA; 83 84 int main(void) 85 { 86 while(~scanf("%d %d", &N, &M) && N && M) 87 { 88 getchar(); 89 ACA.init(); 90 for(int i = 1; i <= N; i++) 91 { 92 char tmp[111]; 93 gets(tmp); 94 ACA.insert(tmp); 95 } 96 ACA.build(); 97 int ans = 0; 98 for(int i = 1; i <= M; i++) 99 { 100 char s[111]; 101 gets(s); 102 ans += ACA.cal(s); 103 } 104 printf("%d\n", ans); 105 } 106 return 0; 107 }
ZOJ 3545 Rescue the Rabbit
更重要的是状压dp的部分。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxnode = 1111, sigma_size = 4; 8 int n, l, w[10]; 9 int dp[2][1111][1111]; 10 11 struct Ac_auto 12 { 13 int Next[maxnode][sigma_size]; 14 int fail[maxnode]; 15 int val[maxnode]; 16 int sz; 17 18 Ac_auto(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 19 void init(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 20 21 int idx(char c) 22 { 23 if(c == 'A') return 0; 24 else if(c == 'G') return 1; 25 else if(c == 'T') return 2; 26 return 3; 27 } 28 29 void insert(char *s, int v) 30 { 31 int u = 0, n = strlen(s); 32 for(int i = 0; i < n; i++) 33 { 34 int c = idx(s[i]); 35 if(!Next[u][c]) 36 { 37 memset(Next[sz], 0, sizeof(Next[sz])); 38 val[sz] = 0; 39 Next[u][c] = sz++; 40 } 41 u = Next[u][c]; 42 } 43 val[u] |= (1 << v); 44 } 45 46 void build() 47 { 48 queue<int> q; 49 fail[0] = 0; 50 for(int i = 0; i < sigma_size; i++) if(Next[0][i]) 51 { 52 fail[Next[0][i]] = 0; 53 q.push(Next[0][i]); 54 } 55 while(!q.empty()) 56 { 57 int pos = q.front(); q.pop(); 58 for(int i = 0; i < sigma_size; i++) 59 { 60 if(!Next[pos][i]) Next[pos][i] = Next[fail[pos]][i]; 61 else 62 { 63 fail[Next[pos][i]] = Next[fail[pos]][i]; 64 q.push(Next[pos][i]); 65 } 66 val[Next[pos][i]] |= val[fail[Next[pos][i]]]; 67 } 68 } 69 } 70 71 void solve() 72 { 73 memset(dp[0], 0, sizeof(dp[0])); 74 dp[0][0][0] = 1; 75 int cur = 1; 76 for(int i = 0; i < l; i++) 77 { 78 memset(dp[cur], 0, sizeof(dp[cur])); 79 cur ^= 1; 80 for(int j = 0; j < sz; j++) 81 { 82 for(int k = 0; k < (1 << n); k++) 83 { 84 if(!dp[cur][j][k]) continue; 85 for(int p = 0; p < 4; p++) dp[cur^1][Next[j][p]][k|val[Next[j][p]]] = 1; 86 } 87 } 88 } 89 int ans = -1; 90 for(int i = 0; i < sz; i++) 91 { 92 for(int j = 0; j < (1 << n); j++) 93 { 94 if(!dp[cur^1][i][j]) continue; 95 int tmp = 0; 96 for(int k = 0; k < n; k++) 97 if( j & (1 << k) ) tmp += w[k]; 98 ans = max(ans, tmp); 99 } 100 } 101 if(ans == -1) puts("No Rabbit after 2012!"); 102 else printf("%d\n", ans); 103 } 104 105 }ACA; 106 107 int main(void) 108 { 109 while(~scanf("%d %d", &n, &l)) 110 { 111 ACA.init(); 112 for(int i = 0; i < n; i++) 113 { 114 char tmp[111]; 115 scanf("%s %d", tmp, w+i); 116 ACA.insert(tmp, i); 117 } 118 ACA.build(); 119 ACA.solve(); 120 } 121 return 0; 122 }
12.9
什么都没干。
12.10
补个CF。
CF 606 C Sorting Railway Cars
和一个BC很像。看最长的连续子列有多长。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int maxn = 1e5 + 10; 5 int a[maxn]; 6 7 int main(void) 8 { 9 int N, Max = 0; 10 scanf("%d", &N); 11 for(int i = 1; i <= N; i++) 12 { 13 int x; 14 scanf("%d", &x); 15 a[x] = 1; 16 a[x] += a[x-1]; 17 if(a[x] > Max) Max = a[x]; 18 } 19 printf("%d\n", N - Max); 20 return 0; 21 }
CF 606 D Lazy Student
构造一颗菊花树即可。加边顺序弄错WA到死。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 typedef long long LL; 6 const int maxn = 1e5 + 10; 7 8 struct edge 9 { 10 int id, used, l; 11 int from, to; 12 }e[maxn]; 13 14 bool cmp1(edge A, edge B) 15 { 16 if(A.l != B.l) return A.l < B.l; 17 return A.used > B.used; 18 } 19 20 bool cmp2(edge A, edge B) 21 { 22 return A.id < B.id; 23 } 24 25 int main(void) 26 { 27 int N, M; 28 scanf("%d%d", &N, &M); 29 for(int i = 1; i <= M; i++) 30 { 31 scanf("%d%d", &e[i].l, &e[i].used); 32 e[i].id = i; 33 } 34 sort(e+1, e+1+M, cmp1); 35 int cnt = 0, tot = 0, ok = 1; 36 for(int i = 1; i <= M; i++) 37 { 38 if(e[i].used) cnt++; 39 else 40 { 41 tot++; 42 if((LL) cnt * (cnt - 1) / 2 < tot) {ok = 0; break;} 43 } 44 } 45 if(ok) 46 { 47 int t1 = 1, t2 = 1; 48 for(int i = 1; i <= M; i++) if(e[i].used) 49 { 50 e[i].from = 1; 51 e[i].to = ++t1; 52 } 53 for(int i = 3; i <= N; i++) 54 { 55 if(t2 > M) break; 56 for(int j = 2; j < i; j++) 57 { 58 if(t2 > M) break; 59 while(e[t2].used) t2++; 60 e[t2].from = i; 61 e[t2].to = j; 62 t2++; 63 } 64 } 65 sort(e+1, e+1+M, cmp2); 66 for(int i = 1; i <= M; i++) printf("%d %d\n", e[i].from, e[i].to); 67 } 68 else puts("-1"); 69 return 0; 70 }
12.11
HDU 3341 Lost's revenge
先是Hash错。自己老是搞很奇怪的Hash。
然后发现了一个AC自动机的写法上的错误。
更新val的时候应该在//的位置。而不是循环外(尽管一些题目是对的。
返回去把写法上不确定的题都重新交了一次。暂无发现问题。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxnode = 555, sigma_size = 4; 8 int N, tot, num[4], o[4], tmp[4], dp[25555][555]; 9 char s[100]; 10 11 struct Ac_auto 12 { 13 int Next[maxnode][sigma_size]; 14 int fail[maxnode]; 15 int val[maxnode]; 16 int sz; 17 18 Ac_auto(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 19 void init(){sz = 1; memset(Next[0], 0, sizeof(Next[0]));} 20 21 int idx(char c) 22 { 23 if(c == 'A') return 0; 24 else if(c == 'G') return 1; 25 else if(c == 'C') return 2; 26 return 3; 27 } 28 29 void insert(char *s) 30 { 31 int u = 0, n = strlen(s); 32 for(int i = 0; i < n; i++) 33 { 34 int c = idx(s[i]); 35 if(!Next[u][c]) 36 { 37 memset(Next[sz], 0, sizeof(Next[sz])); 38 val[sz] = 0; 39 Next[u][c] = sz++; 40 } 41 u = Next[u][c]; 42 } 43 val[u] += 1; 44 } 45 46 void build() 47 { 48 queue<int> q; 49 fail[0] = 0; 50 for(int i = 0; i < sigma_size; i++) if(Next[0][i]) 51 { 52 fail[Next[0][i]] = 0; 53 q.push(Next[0][i]); 54 } 55 while(!q.empty()) 56 { 57 int pos = q.front(); q.pop(); 58 for(int i = 0; i < sigma_size; i++) 59 { 60 if(!Next[pos][i]) Next[pos][i] = Next[fail[pos]][i]; 61 else 62 { 63 fail[Next[pos][i]] = Next[fail[pos]][i]; 64 q.push(Next[pos][i]); 65 val[Next[pos][i]] += val[fail[Next[pos][i]]]; //update val[] 66 } 67 } 68 } 69 } 70 71 int solve() 72 { 73 int ret = 0; 74 memset(dp, -1, sizeof(dp)); 75 dp[0][0] = 0; 76 for(int i = 0; i <= tot; i++) 77 { 78 for(int j = 0; j < sz; j++) 79 { 80 if(dp[i][j] == -1) continue; 81 int p = i; 82 for(int k = 3; k >= 0; k--) tmp[k] = p / num[k], p %= num[k]; 83 for(int k = 0; k < 4; k++) 84 { 85 if(tmp[k] >= o[k]) continue; 86 dp[i+num[k]][Next[j][k]] = max(dp[i+num[k]][Next[j][k]], dp[i][j] + val[Next[j][k]]); 87 } 88 ret = max(ret, dp[i][j]); 89 } 90 } 91 return ret; 92 } 93 94 }ACA; 95 96 int main(void) 97 { 98 int kase = 0; 99 while(~scanf("%d", &N) && N) 100 { 101 ACA.init(); 102 for(int i = 0; i < N; i++) 103 { 104 char tmp[111]; 105 scanf("%s", tmp); 106 ACA.insert(tmp); 107 } 108 ACA.build(); 109 scanf("%s", s); 110 memset(o, 0, sizeof(o)); 111 for(int i = 0; s[i]; i++) 112 { 113 if(s[i] == 'A') o[0]++; 114 else if(s[i] == 'G') o[1]++; 115 else if(s[i] == 'C') o[2]++; 116 else o[3]++; 117 } 118 119 num[0] = 1; 120 num[1] = o[0] + 2; 121 num[2] = num[1] * (o[1] + 1) + 1; 122 num[3] = num[2] * (o[2] + 1) + 1; 123 124 tot = 0; 125 for(int i = 0; i < 4; i++) tot += num[i] * o[i]; 126 127 printf("Case %d: %d\n", ++kase, ACA.solve()); 128 } 129 return 0; 130 }
12.12
打个BC。