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 }
View Code

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 }
View Code

 

posted @ 2018-01-24 11:04  p0ny  阅读(183)  评论(0编辑  收藏  举报