[关闭]
@ljt12138 2017-04-03T19:29:17.000000Z 字数 12543 阅读 924

bzoj刷题记录 4.2-4.4


月考完了。凭借多年应试经验连蒙带猜应付掉,然而坠稳的数学跪烂[没考过班里要学文的dalao]...还是认真刷OJ吧。

bzoj1211:[HNOI2004]树的计数

从Zars19的blog里学习了一个prufer编码。经典文章是matrix67 dalao的介绍,传送门
总之就是把无根有标号树和长度为n2的数组建立了双射,然后树上计数就变成序列计数了。总方案是:

(n2d11)(n2(d11)d21)(n2(d11)(d21)d31))

然而直接组合数莫名其妙的跪,于是阶乘展开变成:

(n2)!i(di1)!

看到阶乘然后就可以上下分解质因数随便减一减就好。另外特判坑死人。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int prime[155], tot = 0;
  4. int n, s, cnt = 0;
  5. int c[155];
  6. void get_prime()
  7. {
  8. for (int i = 2; i <= n; i++) {
  9. int flg = 0;
  10. for (int j = 2; j < i; j++)
  11. if (i%j == 0) {
  12. flg = 1;
  13. break;
  14. }
  15. if (!flg) {
  16. prime[++tot] = i;
  17. for (int j = i; (n-2)/j > 0; j *= i)
  18. c[tot] += (n-2)/j;
  19. }
  20. }
  21. }
  22. void div(int nd)
  23. {
  24. for (int i = 1; i <= tot; i++) {
  25. for (int j = prime[i]; j <= nd; j *= prime[i])
  26. c[i] -= nd/j;
  27. }
  28. }
  29. long long power(int a, int n)
  30. {
  31. if (n == 0) return 1;
  32. long long p = power(a, n>>1);
  33. p *= p, p *= (n&1)?a:1;
  34. return p;
  35. }
  36. int main()
  37. {
  38. scanf("%d", &n);
  39. get_prime();
  40. long long ans = 1;
  41. if (n == 1) {
  42. int d; scanf("%d", &d);
  43. cout << (d == 0) << endl;
  44. return 0;
  45. }
  46. for (int i = 1; i <= n; i++) {
  47. int d; scanf("%d", &d);
  48. if (d == 0) {
  49. cout << 0 << endl;
  50. return 0;
  51. }
  52. div(d-1);
  53. cnt += d-1;
  54. }
  55. if (cnt != n-2) cout << 0 << endl;
  56. else {
  57. for (int i = 1; i <= tot; i++) {
  58. ans *= power(prime[i], c[i]);
  59. }
  60. cout << ans << endl;
  61. }
  62. return 0;
  63. }

bzoj1030:文本生成器

AC自动机上dp处理不包含任何一个串的方案总数,然后减去就好。
顺便熟练一波AC自动机。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. struct ACM {
  4. struct node {
  5. bool finish;
  6. int chl[26], fail;
  7. node():finish(0),fail(0)
  8. { memset(chl, 0, sizeof chl); }
  9. } tree[20005];
  10. int root, top;
  11. queue<int> que;
  12. ACM():root(0),top(0){}
  13. void push(int &nd, const char *str)
  14. {
  15. if (nd == 0) nd = ++top;
  16. if (*str == '\0') tree[nd].finish = 1;
  17. else push(tree[nd].chl[*str-'A'], str+1);
  18. }
  19. void push(const char *str) {push(root, str); }
  20. void init()
  21. {
  22. que.push(root); tree[root].fail = 0;
  23. while (!que.empty()) {
  24. int tp = que.front(); que.pop();
  25. tree[tp].finish |= tree[tree[tp].fail].finish;
  26. for (int i = 0; i < 26; i++) {
  27. if (!tree[tp].chl[i]) continue;
  28. int nd = tree[tp].fail;
  29. while (nd && !tree[nd].chl[i]) nd = tree[nd].fail;
  30. tree[tree[tp].chl[i]].fail = nd?tree[nd].chl[i]:root;
  31. tree[tree[tp].chl[i]].finish |= tree[tp].finish;
  32. que.push(tree[tp].chl[i]);
  33. }
  34. }
  35. }
  36. void dfs(int nd, int tab = 0)
  37. {
  38. if (!nd) return;
  39. for (int i = 1; i <= tab; i++) putchar(' ');
  40. printf("%d(%d, %d) : ", nd, tree[nd].fail, tree[nd].finish);
  41. for (int i = 0; i < 26; i++)
  42. if (tree[nd].chl[i]) printf("--%c--> %d; ", i+'A', tree[nd].chl[i]);
  43. puts("");
  44. for (int i = 0; i < 26; i++)
  45. if (tree[nd].chl[i]) dfs(tree[nd].chl[i], tab+2);
  46. }
  47. } ACM;
  48. int dp[105][20005];
  49. int dfs(int m, int nd)
  50. {
  51. if (ACM.tree[nd].finish) return 0;
  52. if (m == 0) return 1;
  53. if (dp[m][nd] != -1) return dp[m][nd];
  54. dp[m][nd] = 0;
  55. for (int i = 0; i < 26; i++) {
  56. int p = nd;
  57. while (p && !ACM.tree[p].chl[i]) p = ACM.tree[p].fail;
  58. if (p) (dp[m][nd] += dfs(m-1, ACM.tree[p].chl[i])) %= 10007;
  59. else (dp[m][nd] += dfs(m-1, ACM.root)) %= 10007;
  60. }
  61. return dp[m][nd];
  62. }
  63. int power(int a, int n)
  64. {
  65. if (n == 0) return 1;
  66. int p = power(a, n>>1);
  67. (p *= p) %= 10007;
  68. if (n&1) (p *= a) %= 10007;
  69. return p;
  70. }
  71. char str[105];
  72. int n, m;
  73. int main()
  74. {
  75. memset(dp, -1, sizeof dp);
  76. scanf("%d%d", &n, &m);
  77. for (int i = 1; i <= n; i++) {
  78. scanf("%s", str);
  79. ACM.push(str);
  80. }
  81. ACM.init();
  82. int ans = power(26, m)-dfs(m, ACM.root);
  83. ((ans %= 10007) += 10007) %= 10007;
  84. cout << ans << endl;
  85. return 0;
  86. }

bzoj1016:[JSOI2008]最小生成树计数

原来讲过的题然而一直没有做。
按边长从小到大排,每次做一个Matrix_Tree生成森林计数,然后把能缩的缩在一起。除了特判1A。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 105, MAXM = 1005;
  4. struct node {
  5. int i, j, d;
  6. friend bool operator < (const node &a, const node &b)
  7. { return a.d < b.d; }
  8. } edge[MAXM];
  9. int n, m;
  10. int gp[MAXN], vis[MAXN], gt; // 缩在一起的点的新编号
  11. double g[MAXN][MAXN]; // 求解行列式
  12. struct ufs {
  13. int fa[MAXN];
  14. void clear()
  15. { memset(fa, 0, sizeof fa); }
  16. ufs(){clear(); }
  17. inline int findf(int nd)
  18. { return fa[nd]?fa[nd] = findf(fa[nd]):nd; }
  19. void link(int i, int j)
  20. {
  21. int p = findf(i), q = findf(j);
  22. if (p != q) fa[p] = q;
  23. }
  24. } UFS, u2;
  25. int calc()
  26. {
  27. if (gt == 0) return 1;
  28. gt--;
  29. double ans = 1;
  30. for (int i = 1; i <= gt; i++) {
  31. if (g[i][i] == 0) {
  32. int k = i+1; while (!g[k][i]) k++;
  33. swap(g[i], g[k]);
  34. }
  35. ans *= g[i][i];
  36. for (int j = i+1; j <= gt; j++) {
  37. double t = -g[j][i]/g[i][i];
  38. for (int k = i; k <= gt; k++)
  39. g[j][k] += g[i][k]*t;
  40. }
  41. }
  42. // cout << ans << endl;
  43. return int(ans+0.05)%31011;
  44. }
  45. int main()
  46. {
  47. scanf("%d%d", &n, &m);
  48. for (int i = 1; i <= m; i++)
  49. scanf("%d%d%d", &edge[i].i, &edge[i].j, &edge[i].d);
  50. sort(edge+1, edge+m+1);
  51. long long ans = 1;
  52. for (int i = 1; i <= m; ) {
  53. // cout << "--" << i <<" " << edge[i].d<< endl;
  54. int d = edge[i].d;
  55. memset(vis, 0, sizeof vis);
  56. memset(g, 0, sizeof g);
  57. u2.clear();
  58. gt = 0;
  59. for (int j = i; j <= m && edge[j].d == d; j++) {
  60. int p = UFS.findf(edge[j].i), q = UFS.findf(edge[j].j);
  61. if (p==q) continue;
  62. if (!vis[p]) gp[p] = ++gt, vis[p] = 1;
  63. if (!vis[q]) gp[q] = ++gt, vis[q] = 1;
  64. g[gp[p]][gp[q]]--, g[gp[q]][gp[p]]--, g[gp[p]][gp[p]]++, g[gp[q]][gp[q]]++, u2.link(gp[p], gp[q]);
  65. } // 建图
  66. if (gt == 1) break;
  67. for (int k = 1; k <= gt; k++)
  68. for (int j = k+1; j <= gt; j++) {
  69. // cout << k << " " << j << endl;
  70. if (u2.findf(k) != u2.findf(j))
  71. u2.link(k, j), g[k][j] = g[j][k] = -1, g[k][k]++, g[j][j]++;
  72. }
  73. // 建桥
  74. (ans *= calc()) %= 31011; // matrix_tree theory
  75. while (edge[i].d == d) UFS.link(edge[i].i, edge[i].j), i++; // 合并
  76. }
  77. for (int i = 1; i <= n; i++)
  78. for (int j = 1; j <= n; j++)
  79. if (UFS.findf(i) != UFS.findf(j)) {
  80. cout << 0 << endl;
  81. return 0;
  82. }
  83. cout << ans << endl;
  84. return 0;
  85. }

bzoj1004: [HNOI2008]Cards

居然自己看并1A了这置换群...
首先奇奇怪怪的表述让我们知道出题人要告诉我们是个置换群:

  1. 输入数据保证任意多次洗牌都可用这m种洗牌法中的一种代替——运算封闭;
  2. 置换显然满足结合律、交换律;
  3. 且对每种洗牌法,都存在一种洗牌法使得能回到原状态——每个元素都可逆;
  4. 有没有幺元你加一个不就有了吗?

然后就可以做波利亚计数了。dp预处理每个置换下不变(环内染一种色)的方案数,求和算平均。为了防止重复置换,加一个哈希判重。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 70;
  4. int Sr, Sb, Sg, m, p, n;
  5. int power(int a, int n)
  6. {
  7. if (n == 0) return 1;
  8. int k = power(a, n>>1);
  9. (k *= k) %= p, (k *= (n&1)?a:1) %= p;
  10. return k;
  11. }
  12. int inv(int a)
  13. { return power(a, p-2); }
  14. int fa[MAXN], siz[MAXN], per[MAXN];
  15. inline int findf(int nd)
  16. { return fa[nd]?fa[nd] = findf(fa[nd]):nd; }
  17. inline void link(int a, int b)
  18. {
  19. int p = findf(a), q = findf(b);
  20. if (p != q) fa[p] = q, siz[q] += siz[p];
  21. }
  22. int ht[MAXN], gt = 0;
  23. int dp[MAXN][21][21][21]; // dp嘛..
  24. int cnp = 0; // |G| 波利亚计数原理
  25. // ------
  26. // 哈希表 防止重复而gg
  27. int hsh[3214567];
  28. int hash_p(int p[])
  29. {
  30. unsigned int val = 0, bs = 1;
  31. for (int i = 1; i <= n; i++) {
  32. val += p[i]*bs;
  33. bs *= (n+1);
  34. }
  35. return val%3214567;
  36. }
  37. // ------
  38. int val(int pp[MAXN]) // 计算某一置换下不变的方案数, dp
  39. {
  40. int k = hash_p(pp);
  41. if (hsh[k] == 1) return 0;
  42. else hsh[k] = 1, cnp++;
  43. memset(fa, 0, sizeof fa);
  44. for (int i = 1; i <= n; i++) siz[i] = 1;
  45. for (int i = 1; i <= n; i++) link(i, pp[i]);
  46. gt = 0;
  47. for (int i = 1; i <= n; i++)
  48. if (fa[i] == 0)
  49. ht[++gt] = siz[i];
  50. memset(dp, 0, sizeof dp);
  51. dp[0][0][0][0] = 1;
  52. for (int i = 1; i <= gt; i++)
  53. for (int j = 0; j <= Sr; j++)
  54. for (int k = 0; k <= Sg; k++)
  55. for (int l = 0; l <= Sb; l++) {
  56. if (j>=ht[i]) (dp[i][j][k][l] += dp[i-1][j-ht[i]][k][l]) %= p;
  57. if (k>=ht[i]) (dp[i][j][k][l] += dp[i-1][j][k-ht[i]][l]) %= p;
  58. if (l>=ht[i]) (dp[i][j][k][l] += dp[i-1][j][k][l-ht[i]]) %= p;
  59. }
  60. // cout << dp[gt][Sr][Sg][Sb] << endl;
  61. return dp[gt][Sr][Sg][Sb];
  62. }
  63. int main()
  64. {
  65. scanf("%d%d%d%d%d", &Sr, &Sg, &Sb, &m, &p);
  66. n = Sr + Sg + Sb;
  67. int ans = 0;
  68. for (int i = 1; i <= n; i++) per[i] = i; // 加个幺元
  69. (ans += val(per)) %= p;
  70. for (int i = 1; i <= m; i++) {
  71. for (int j = 1; j <= n; j++) scanf("%d", &per[j]);
  72. (ans += val(per)) %= p;
  73. }
  74. cout << ans*inv(cnp)%p << endl;
  75. return 0;
  76. }

1007: [HNOI2008]水平可见直线

水水的半平面交?都是大于号,用一个栈处理就好了,甚至不需要计算几何知识就能脑补1A...五道题打卡下班。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. struct hp {
  4. double a, b;
  5. int id;
  6. hp(){}
  7. hp(double x, double y, int i):a(x),b(y),id(i){}
  8. friend bool operator < (const hp &a, const hp &b)
  9. { return a.a==b.a?a.b>b.b:a.a < b.a; }
  10. } sg[50005];
  11. int n;
  12. stack<int> stk;
  13. int ptw[50005], tp = 0;
  14. bool onleft(const hp &a, const hp &b, const hp &sd)
  15. {
  16. double x = (b.b-a.b)/(a.a-b.a), y = a.a*x+a.b;
  17. return y+1e-7 >= sd.a*x+sd.b;
  18. }
  19. int main()
  20. {
  21. scanf("%d", &n);
  22. for (int i = 1; i <= n; i++) {
  23. double a, b;
  24. scanf("%lf%lf", &a, &b);
  25. sg[i] = hp(a, b, i);
  26. }
  27. sort(sg+1, sg+n+1);
  28. int nw = n;
  29. for (int i = 1; i <= n; i++)
  30. if (sg[i].a == sg[i-1].a) {
  31. sg[i].a = INT_MAX;
  32. nw--;
  33. }
  34. sort(sg+1, sg+n+1);
  35. n = nw;
  36. for (int i = 1; i <= n; i++) {
  37. // cout << sg[i].id << endl;
  38. while (stk.size() >= 2) {
  39. int tp = stk.top(); stk.pop();
  40. int t2 = stk.top(); stk.pop();
  41. if (onleft(sg[i], sg[t2], sg[tp])) stk.push(t2);
  42. else {stk.push(t2), stk.push(tp); break;}
  43. }
  44. stk.push(i);
  45. }
  46. while (!stk.empty()) ptw[++tp] = sg[stk.top()].id, stk.pop();
  47. sort(ptw+1, ptw+tp+1);
  48. for (int i = 1; i <= tp; i++)
  49. printf("%d ", ptw[i]);
  50. return 0;
  51. }

bzoj1015: [JSOI2008]星球大战starwar

删除难而加入容易,只要反过来做就好了。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 400005, MAXM = 200005;
  4. struct edge {
  5. int s, t;
  6. } graph[MAXM];
  7. struct node {
  8. int to, next;
  9. } edge_list[2*MAXM];
  10. int head[MAXN], top = 0;
  11. inline void push(int i, int j)
  12. { ++top, edge_list[top] = (node) {j, head[i]}, head[i] = top; }
  13. int n, m;
  14. int q[MAXN], l = 0;
  15. int fa[MAXN];
  16. int vis[MAXN], ans[MAXN], cnt, del = 0; // cnt : 联通块个数
  17. inline int findf(int i)
  18. { return fa[i]!=-1?fa[i]=findf(fa[i]):i; }
  19. void link(int i, int j)
  20. {
  21. int p = findf(i), q = findf(j);
  22. if (p != q) {
  23. fa[p] = q;
  24. cnt--;
  25. }
  26. }
  27. int main()
  28. {
  29. memset(fa, -1, sizeof fa);
  30. memset(head, -1, sizeof head);
  31. scanf("%d%d", &n, &m);
  32. for (int i = 1; i <= m; i++) {
  33. scanf("%d%d", &graph[i].s, &graph[i].t);
  34. push(graph[i].s, graph[i].t), push(graph[i].t, graph[i].s);
  35. }
  36. scanf("%d", &l);
  37. for (int i = 1; i <= l; i++) scanf("%d", &q[i]), vis[q[i]] = i;
  38. // for (int i = 1; i <= l; i++) cout << vis[q[i]] << " "; puts("");
  39. cnt = n;
  40. for (int i = 1; i <= l; i++) del += vis[q[i]] == i;
  41. for (int i = 1; i <= m; i++)
  42. if (!vis[graph[i].s] && !vis[graph[i].t])
  43. link(graph[i].s, graph[i].t);
  44. for (int i = l; i >= 1; i--) {
  45. ans[i] = cnt-del;
  46. // cout << del << endl;
  47. if (vis[q[i]] == i) {
  48. del--;
  49. vis[q[i]] = 0;
  50. for (int j = head[q[i]]; j != -1; j = edge_list[j].next) {
  51. int to = edge_list[j].to;
  52. if (vis[to] == 0)
  53. link(q[i], to);
  54. }
  55. }
  56. }
  57. cout << cnt << endl;
  58. for (int i = 1; i <= l; i++)
  59. printf("%d\n", ans[i]);
  60. return 0;
  61. }

bzoj2242: [SDOI2011]计算器

数论模板题,复习bsgs。
注意bsgs的第二步求逆要在循环外求,否则会被肉眼可见卡常数。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. long long y, z, p;
  4. int t, k;
  5. long long power(long long a, long long n)
  6. {
  7. if (a == 0) return 0;
  8. if (n == 0) return 1;
  9. long long k = power(a, n>>1);
  10. (k *= k) %= p;
  11. if (n&1) (k *= a) %= p;
  12. return k;
  13. }
  14. long long inv(long long a)
  15. { return power(a, p-2); }
  16. map<long long, long long> hsh;
  17. void work()
  18. {
  19. if (k == 1) {
  20. printf("%lld\n", power(y, z));
  21. } else if (k == 2) {
  22. long long x = inv(y)*z%p;
  23. if (x > 0 && x*y%p == z%p) printf("%lld\n", x);
  24. else puts("Orz, I cannot find x!");
  25. } else {
  26. y %= p, z %= p;
  27. if (y == 0 && z == 0) {puts("1");return;}
  28. if (y == 0) {puts("Orz, I cannot find x!"); return;}
  29. hsh.clear();
  30. long long tp = ceil(sqrt(p)+1e-7);
  31. long long delta = 1;
  32. for (int i = 1; i <= tp; i++) {
  33. (delta *= y) %= p;
  34. if (!hsh.count(delta))hsh[delta] = i;
  35. }
  36. long long bs = 1;
  37. bool fd = 0;
  38. delta = inv(delta);
  39. for (int i = 0; i*tp <= p; i++) {
  40. if (hsh.count(bs*z%p)) {
  41. // cout << i*tp << " " << bs << " " << inv(bs) << " " << hsh[inv(bs)] << endl;
  42. printf("%lld\n", i*tp+hsh[bs*z%p]);
  43. fd = 1;
  44. break;
  45. }
  46. (bs *= delta) %= p;
  47. }
  48. if (!fd) puts("Orz, I cannot find x!");
  49. }
  50. }
  51. int main()
  52. {
  53. scanf("%d%d", &t, &k);
  54. for (int i = 1; i <= t; i++) {
  55. scanf("%lld%lld%lld", &y, &z, &p);
  56. work();
  57. }
  58. return 0;
  59. }

bzoj1014: [JSOI2008]火星人prefix

一遇数据结构就跪综合症...因为位置和树上位置的转化调了一个多小时。

首先“插入不超过10000个”可以想到是O(lg2n)的插入,就是二分+哈希了。然而哈希是动态的,于是要splay维护。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXM = 2000005;
  4. int chl[MAXM][2];
  5. unsigned long long dat[MAXM], cha[MAXM], power[MAXM];
  6. unsigned int siz[MAXM], fa[MAXM];
  7. int top = 0, root = 0;
  8. inline int new_node(char c, int f)
  9. { return ++top, dat[top] = cha[top] = c-'a'+1, siz[top] = 1, fa[top] = f, top; }
  10. void update(int nd)
  11. {
  12. siz[nd] = siz[chl[nd][0]] + siz[chl[nd][1]] + 1;
  13. dat[nd] = dat[chl[nd][0]] + power[siz[chl[nd][0]]]*(cha[nd] + (unsigned long long)27*dat[chl[nd][1]]);
  14. }
  15. void zig(int nd)
  16. {
  17. // cout << "zigging : " << nd << endl;
  18. int p = fa[nd], g = fa[fa[nd]], tp = chl[p][0] != nd;
  19. int tg = chl[g][0] != p, son = chl[nd][tp^1];
  20. if (son) fa[son] = p; fa[p] = nd, fa[nd] = g;
  21. if (g) chl[g][tg] = nd;
  22. else root = nd;
  23. chl[nd][tp^1] = p, chl[p][tp] = son;
  24. update(p), update(nd);
  25. }
  26. void dfs(int nd, int tab = 0)
  27. {
  28. if (!nd) return;
  29. for (int i = 0; i < tab; i++) cout << " ";
  30. printf("%d--%c--(%d,%d), siz = %d, fa = %d\n", nd, cha[nd], chl[nd][0], chl[nd][1], siz[nd], fa[nd]);
  31. dfs(chl[nd][0], tab+2);
  32. dfs(chl[nd][1], tab+2);
  33. }
  34. void splay(int nd, int tar = 0)
  35. {
  36. // cout << "splaying : " << nd << " --> son of " << tar << endl;
  37. while (fa[nd] != tar) {
  38. // cout << nd << endl;
  39. int p = fa[nd], g = fa[nd], tp = chl[p][0] != nd, tg = chl[g][0] != p;
  40. if (fa[p] == tar) {zig(nd); break;}
  41. if (tp == tg) zig(p), zig(nd);
  42. else zig(nd), zig(nd);
  43. }
  44. } // splay tree
  45. int position(int k)
  46. {
  47. if (k > siz[root] || k <= 0) return 0;
  48. k--;
  49. int nd = root;
  50. while (k != siz[chl[nd][0]]) {
  51. // cout << nd << " " << k << endl;
  52. nd = (siz[chl[nd][0]] > k) ? (chl[nd][0]) : (k -= siz[chl[nd][0]]+1, chl[nd][1]);
  53. }
  54. return nd;
  55. } // get the position of k-th element
  56. int segment(int l, int r)
  57. {
  58. int k = position(l-1), p = position(r+1);
  59. if (l == 1 && r == siz[root]) return root;
  60. if (l == 1) return splay(p), chl[root][0];
  61. if (r == siz[root]) return splay(k), chl[root][1];
  62. return splay(k), splay(p, root), chl[chl[root][1]][0];
  63. } // get a segment [l, r]
  64. unsigned long long query(int l, int r)
  65. { return dat[segment(l, r)]; } // get the hash value in [l, r]
  66. void insert(int k, char c) // push a new element after k-th element
  67. {
  68. // cout << k << " " << c << " " << siz[root] << endl;
  69. if (!root && k == 0) {
  70. root = new_node(c, 0);
  71. return;
  72. } // no element
  73. if (k == 0) {
  74. splay(position(1));
  75. chl[root][0] = new_node(c, root);
  76. update(root);
  77. } else {
  78. int nd = segment(k, k);
  79. // puts("-----"); dfs(root);
  80. chl[nd][1] = new_node(c, nd);
  81. while (nd)
  82. update(nd), nd = fa[nd];
  83. }
  84. // dfs(root);
  85. }
  86. void change(int k, char c)
  87. { splay(k), cha[k] = c-'a'+1, update(k);
  88. } // change the value of an existed element
  89. void init()
  90. {
  91. power[0] = 1;
  92. for (int i = 1; i < MAXM; i++)
  93. power[i] = power[i-1]*27;
  94. // power for hash
  95. }
  96. // -------------
  97. int ask(int opl, int opr)
  98. {
  99. int len = siz[root]; // maxlen
  100. int l = 0, r = len-max(opl, opr)+1;
  101. while (l <= r) {
  102. int mid = (l+r)>>1;
  103. if (query(opl, opl+mid-1) == query(opr, opr+mid-1)) l = mid+1;
  104. else r = mid-1;
  105. }
  106. return l-1;
  107. }
  108. int n;
  109. char str[MAXM];
  110. char get_char()
  111. {
  112. char c;
  113. do c = getchar(); while(!isalpha(c));
  114. return c;
  115. }
  116. inline int read() {
  117. int a = 0, c;
  118. do c = getchar(); while(!isdigit(c));
  119. while (isdigit(c)) {
  120. a = a*10+c-'0';
  121. c = getchar();
  122. }
  123. return a;
  124. }
  125. int main()
  126. {
  127. init();
  128. scanf("%s", str);
  129. for (int i = 0, l = strlen(str); i < l; i++)
  130. insert(i, str[i]); // build a tree
  131. n = read();
  132. int cnt = 0;
  133. for (int i = 1; i <= n; i++) {
  134. char c = get_char();
  135. int l, r, p; char d;
  136. switch (c) {
  137. case 'Q':
  138. cnt++;
  139. l = read(), r = read();
  140. printf("%d\n", ask(l, r));
  141. break;
  142. case 'R':
  143. p = read(), d = get_char();
  144. if (!isalpha(d)) throw;
  145. change(position(p), d);
  146. break;
  147. case 'I':
  148. p = read(), d = get_char();
  149. if (!isalpha(d)) throw;
  150. insert(p, d);
  151. break;
  152. default:
  153. throw;
  154. break;
  155. }
  156. }
  157. return 0;
  158. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注