Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined)
Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) |
---|
A.模拟
B.只要有一个数字出现的次数是奇数就不会输。
C.因为n的二进制位上最多只有1000个1,所以我们可以暴力预处理出$1 \cdots 1000$变成$1$的步数。
枚举n的每一位。如果这一位是1,把它变成0就可以保证一定比n小。比i高的位跟n一样,计算从低位选出若干个1的方案数。
D.线段树维护区间gcd。查询的时候如果不同就进去看一看。
E.点分治啦。把每个字符都表示成二进制上的某一位。注意root的处理。要么add的时候不算root,query时算;要么add的时候算root,query时不算。(这里的算指的是字符的xor那些东西)
1 #include<vector> 2 #include<bitset> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #define pb push_back 7 using namespace std; 8 typedef long long ll; 9 int n, cnt[1<<20], vis[200005], R, sz[200005], mx[200005], size; 10 ll ans[200005], tans; 11 char a[200005]; 12 vector < int > g[200005]; 13 inline void gmax(int &x, int y) {if (x < y) x = y;} 14 void getR(int u, int f) { 15 sz[u] = 1; mx[u] = 0; 16 for (int i = 0, v; i < g[u].size(); ++i) 17 if (!vis[v=g[u][i]] && v != f) { 18 getR(v, u); sz[u] += sz[v]; 19 gmax(mx[u], sz[v]); 20 } 21 gmax(mx[u], size - sz[u]); 22 if (mx[u] < mx[R]) R = u; 23 } 24 ll upd(int val) { 25 ll res = cnt[val]; 26 for (int i = 0; i < 20; ++i) 27 res += cnt[val^(1<<i)]; 28 return res; 29 } 30 ll upd(int u, int f, int val) { 31 val ^= 1 << a[u]; ll res = upd(val); 32 for (int i = 0, v; i < g[u].size(); ++i) 33 if (!vis[v=g[u][i]] && v != f) res += upd(v, u, val); 34 ans[u] += res; 35 return res; 36 } 37 void add(int u, int f, int val) { 38 val ^= 1 << a[u]; ++cnt[val]; 39 for (int i = 0, v; i < g[u].size(); ++i) 40 if (!vis[v=g[u][i]] && v != f) add(v, u, val); 41 } 42 void del(int u, int f, int val) { 43 val ^= 1 << a[u]; --cnt[val]; 44 for (int i = 0, v; i < g[u].size(); ++i) 45 if (!vis[v=g[u][i]] && v != f) del(v, u, val); 46 } 47 void solve(int u) { 48 vis[u] = 1; add(u, u, 0); tans = upd(0); 49 for (int v, i = 0; i < g[u].size(); ++i) 50 if (!vis[v=g[u][i]]) del(v, u, 1 << a[u]), tans += upd(v, u, 0), add(v, u, 1 << a[u]); 51 ans[u] += tans / 2; del(u, u, 0); 52 for (int v, i = 0; i < g[u].size(); ++i) 53 if (!vis[v=g[u][i]]) size = sz[v], getR(v, R = 0), solve(R); 54 } 55 int main() { 56 scanf("%d", &n); mx[0] = 0x3f3f3f3f; size = n; 57 for (int u, v, i = 1; i < n; ++i) 58 scanf("%d%d", &u, &v), g[u].pb(v), g[v].pb(u); 59 scanf("%s", a + 1); 60 for (int i = 1; i <= n; ++i) a[i] -= 'a'; 61 getR(1, 1); solve(R); 62 for (int i = 1; i <= n; ++i) 63 printf("%lld%c", ans[i] + 1, " \n"[i==n]); 64 return 0; 65 }
F.bitset。。。
1 #include<bitset> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 bitset < 100005 > s[30], ans, U; 7 char str[100005], buf[100005]; 8 int main() { 9 scanf("%s", str + 1); 10 int n = strlen(str + 1), m; 11 for (int i = 1; i <= n; ++i) 12 s[str[i]-'a'][i] = 1; 13 for (int i = 0; i < n; ++i) U[i] = 1; 14 scanf("%d", &m); 15 while (m--) { 16 int op, l, r; 17 scanf("%d", &op); 18 if (op == 1) { 19 scanf("%d%s", &l, buf + 1); 20 s[str[l]-'a'][l] = 0; 21 str[l] = buf[1]; 22 s[str[l]-'a'][l] = 1; 23 } else { 24 scanf("%d%d%s", &l, &r, buf + 1); 25 int len = strlen(buf + 1); 26 if (len > r - l + 1) { 27 puts("0"); continue; 28 } 29 ans = U; 30 for (int i = 1; i <= len; ++i) 31 ans &= (s[buf[i]-'a']>>i); 32 printf("%d\n", (ans>>(l-1)).count() - (ans>>(r-len+1)).count()); 33 } 34 } 35 return 0; 36 }