BZOJ3238 [Ahoi2013]差异
2015-05-03 22:17
218 查看
首先把后缀数组和height数组都搞出来。。。
然后用两个单调栈维护$[l, r]$表示对于一个点$x$,满足$height[x] \le height[l..x] \ \&\&\ height[x] < height[x..r]$的最小的$l$和最大的$r$
这样子就可以保证不会重复计算了
View Code
然后用两个单调栈维护$[l, r]$表示对于一个点$x$,满足$height[x] \le height[l..x] \ \&\&\ height[x] < height[x..r]$的最小的$l$和最大的$r$
这样子就可以保证不会重复计算了
/************************************************************** Problem: 3238 User: rausen Language: C++ Result: Accepted Time:4496 ms Memory:20336 kb ****************************************************************/ #include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int N = 5e5 + 5; int a , len; int sa , rank , height ; inline void Sort(int *a, int *b, int *c, int n, int m) { static int i, sum ; for (i = 0; i <= m; ++i) sum[i] = 0; for (i = 0; i < n; ++i) ++sum[c[a[i]]]; for (i = 1; i <= m; ++i) sum[i] += sum[i - 1]; for (i = n - 1; ~i; --i) b[--sum[c[a[i]]]] = a[i]; } void make_sa(int *s) { int i, j; static int x , y ; for (i = 0; i < len; ++i) x[i] = s[i], rank[i] = i; Sort(rank, sa, x, len, 30); rank[sa[0]] = 1; for (i = 1; i < len; ++i) rank[sa[i]] = rank[sa[i - 1]] + (x[sa[i]] != x[sa[i - 1]]); for (i = 1; i <= len; i <<= 1) { for (j = 0; j < len; ++j) x[j] = rank[j], y[j] = j + i < len ? rank[j + i] : 0, sa[j] = j; Sort(sa, rank, y, len, len), Sort(rank, sa, x, len, len); rank[sa[0]] = 1; for (j = 1; j < len; ++j) rank[sa[j]] = rank[sa[j - 1]] + (x[sa[j]] != x[sa[j - 1]] || y[sa[j]] != y[sa[j - 1]]); if (rank[sa[len - 1]] == len) return; } } void make_height() { int i, j; for (i = j = 0; i < len; ++i) { if (j) --j; if (rank[i] != 1) while (a[i + j] == a[sa[rank[i] - 2] + j]) ++j; height[rank[i]] = j; } } ll work() { int i; ll res; static int s , top, l , r ; for (res = 0, i = 1; i <= len; ++i) res += 1ll * i * (len - 1); for (s[top = 0] = 0, i = 1; i <= len; ++i) { while (height[i] <= height[s[top]] && top) --top; l[i] = s[top] + 1; s[++top] = i; } for (s[top = 0] = len + 1, i = len; i; --i) { while (height[i] < height[s[top]] && top) --top; r[i] = s[top] - 1; s[++top] = i; } for (i = 1; i <= len; ++i) res -= 2ll * (i - l[i] + 1) * (r[i] - i + 1) * height[i]; return res; } int main() { int i; char ch; for (len = 0; ;) { ch = getchar(); if ('a' <= ch && ch <= 'z') a[len++] = ch - 'a' + 1; else break; } make_sa(a); make_height(); printf("%lld\n", work()); return 0; }
View Code
相关文章推荐
- bzoj3238: [Ahoi2013]差异
- [Ahoi2013]差异 bzoj3238
- BZOJ3238: [Ahoi2013]差异
- bzoj3238 [Ahoi2013]差异
- Bzoj3238: [Ahoi2013]差异
- Bzoj3238: [Ahoi2013]差异
- BZOJ3238:[AHOI2013]差异——题解
- bzoj3238 [Ahoi2013]差异(SA+单调栈求所有区间最小值和)
- bzoj3238 [Ahoi2013]差异
- bzoj 3238: [Ahoi2013]差异 后缀数组
- bzoj 3238 [Ahoi2013]差异
- 【bzoj3238】[Ahoi2013]差异 后缀数组+单调栈
- BZOJ3238:[AHOI 2013]差异
- BZOJ 3238 [Ahoi2013] 差异 | 后缀数组 单调栈
- bzoj3238 [Ahoi2013]差异
- [AHOI2013]差异
- bzoj3238: [Ahoi2013]差异
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
- bzoj3238 [ AHOI2013 ] --后缀自动机
- 【AHOI2013】【BZOJ3238】差异