记录编号 377927 评测结果 AAAAAAAAAA
题目名称 [HZOI 2016][GDOI2016模拟3.14] hashit 最终得分 100
用户昵称 Gravatar半汪 是否通过 通过
代码语言 C++ 运行时间 0.412 s
提交时间 2017-03-02 18:04:54 内存使用 4.58 MiB
显示代码纯文本
  1. #include <cstring>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <ctime>
  5.  
  6. using namespace std;
  7. typedef unsigned long long LL;
  8.  
  9. const int MAXN = 1e5 + 5;
  10. const int Pri = 9973;
  11. const LL Inf = 1ll << 62;
  12.  
  13. struct SuffixBalanceTree {
  14. LL tag;
  15. int Son[2], Size, fix;
  16. } Tr[MAXN];
  17.  
  18. int tot, Root, Lcp[MAXN];
  19. char S[MAXN];
  20. LL Del, Pow[MAXN], Has[MAXN];
  21.  
  22. bool Cmp(int x, int y) {
  23. return S[x] < S[y] || S[x] == S[y] && Tr[x - 1].tag < Tr[y - 1].tag;
  24. }
  25.  
  26. void Clear(int x, LL l, LL r) {
  27. Tr[x].fix = rand();
  28. Tr[x].Son[0] = Tr[x].Son[1] = 0;
  29. Tr[x].Size = 1;
  30. Tr[x].tag = (l + r) >> 1;
  31. }
  32.  
  33. void Update(int Now, LL l, LL r) {
  34. if (!Now) return;
  35. Tr[Now].tag = (l + r) >> 1;
  36. LL Mid = (l + r) >> 1;
  37. Update(Tr[Now].Son[0], l, Mid), Update(Tr[Now].Son[1], Mid + 1, r);
  38. Tr[Now].Size = Tr[Tr[Now].Son[0]].Size + Tr[Tr[Now].Son[1]].Size + 1;
  39. }
  40.  
  41. void Rotate(int Now, int Pre, LL l, LL r) {
  42. int Side = Tr[Pre].Son[1] == Now;
  43. Tr[Pre].Son[Side] = Tr[Now].Son[Side ^ 1];
  44. Tr[Now].Son[Side ^ 1] = Pre;
  45. Update(Now, l, r);
  46. }
  47.  
  48. void Insert(int &Now, LL l, LL r) {
  49. if (!Now) {
  50. Now = tot;
  51. Clear(Now, l, r);
  52. return;
  53. }
  54. Tr[Now].Size ++;
  55. LL Mid = (l + r) >> 1;
  56. if (Cmp(tot, Now)) Insert(Tr[Now].Son[0], l, Mid); else
  57. Insert(Tr[Now].Son[1], Mid + 1, r);
  58. if (Tr[tot].fix > Tr[Now].fix) {
  59. Rotate(tot, Now, l, r);
  60. Now = tot;
  61. }
  62. }
  63.  
  64. int GetRank(int Now) {
  65. if (Now == tot) return Tr[Tr[Now].Son[0]].Size + 1;
  66. if (Cmp(tot, Now)) return GetRank(Tr[Now].Son[0]);
  67. return Tr[Tr[Now].Son[0]].Size + 1 + GetRank(Tr[Now].Son[1]);
  68. }
  69.  
  70. int Search(int Now, int rk) {
  71. if (!Now) return Now;
  72. if (Tr[Tr[Now].Son[0]].Size + 1 == rk) return Now;
  73. if (Tr[Tr[Now].Son[0]].Size >= rk) return Search(Tr[Now].Son[0], rk);
  74. return Search(Tr[Now].Son[1], rk - Tr[Tr[Now].Son[0]].Size - 1);
  75. }
  76.  
  77. bool Same(int l1, int l2, int len) {
  78. int r1 = l1 + len - 1, r2 = l2 + len - 1;
  79. return Has[r1] - Has[l1 - 1] * Pow[len] == Has[r2] - Has[l2 - 1] * Pow[len];
  80. }
  81.  
  82. int TreatLcp(int x, int y) {
  83. int l = 1, r = min(x, y), Ans = 0;
  84. while (l <= r) {
  85. int Mid = (l + r) >> 1;
  86. if (Same(x - Mid + 1, y - Mid + 1, Mid)) Ans = Mid, l = Mid + 1; else
  87. r = Mid - 1;
  88. }
  89. Lcp[y] = Ans;
  90. }
  91.  
  92. void Add(char c) {
  93. S[++ tot] = c;
  94. Has[tot] = Has[tot - 1] * Pri + S[tot] - 'a' + 1;
  95. Insert(Root, 1, Inf);
  96. int rk = GetRank(Root);
  97. int l = Search(Root, rk - 1), r = Search(Root, rk + 1);
  98. Del = Del - Lcp[r];
  99. TreatLcp(l, tot), TreatLcp(tot, r);
  100. Del = Del + Lcp[tot] + Lcp[r];
  101. }
  102.  
  103. int Merge(int a, int b) {
  104. if (!a) return b;
  105. if (!b) return a;
  106. if (Tr[a].fix < Tr[b].fix) {
  107. Tr[b].Son[0] = Merge(a, Tr[b].Son[0]);
  108. return b;
  109. }
  110. Tr[a].Son[1] = Merge(Tr[a].Son[1], b);
  111. return a;
  112. }
  113.  
  114. void Out(int &Now, LL l, LL r) {
  115. if (tot == Now) {
  116. Now = Merge(Tr[Now].Son[0], Tr[Now].Son[1]);
  117. Update(Now, l, r);
  118. } else {
  119. Tr[Now].Size --;
  120. LL Mid = (l + r) >> 1;
  121. if (Cmp(tot, Now)) Out(Tr[Now].Son[0], l, Mid); else
  122. Out(Tr[Now].Son[1], Mid + 1, r);
  123. }
  124. }
  125.  
  126. void Delete() {
  127. int rk = GetRank(Root);
  128. int l = Search(Root, rk - 1), r = Search(Root, rk + 1);
  129. Del = Del - Lcp[tot] - Lcp[r];
  130. TreatLcp(l, r);
  131. Del = Del + Lcp[r];
  132. Out(Root, 1, Inf);
  133. tot --;
  134. }
  135.  
  136. int main() {
  137. freopen("hahaha.in","r",stdin);freopen("hahaha.out","w",stdout);
  138. int len;
  139. scanf("%d",&len);
  140. scanf("%s", S + 1);
  141. Pow[0] = 1;
  142. for (int i = 1; i <= len; i ++) Pow[i] = Pow[i - 1] * Pri;
  143. for (int i = 1; i <= len; i ++) {
  144. if (S[i] == '-') Delete(); else
  145. Add(S[i]);
  146. printf("%lld\n", 1ll * tot * (tot + 1) / 2 - Del);
  147. }
  148. }