EntropyIncreaser

SDOI2016 生成魔咒

Jan 17th, 2018
390
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.60 KB | None | 0 0
  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. #include <algorithm>
  5. #include <set>
  6.  
  7. using namespace std;
  8.  
  9. typedef long long ll;
  10. typedef set<int> set_t;
  11.  
  12. const int N = 100010;
  13.  
  14. struct {
  15.     int a, b, id;
  16. } p[N], q[N];
  17.  
  18. struct node {
  19.     int l, r, d;
  20.     node *ls, *rs;
  21.  
  22.     int query(int l, int r) const;
  23. };
  24.  
  25. int n;
  26. int a[N], sa[N], rk[N], cnt[N], sorted[N], h[N], height[N];
  27.  
  28. node* build(int l, int r);
  29.  
  30. int main() {
  31.     ll hsum = 0;
  32.     scanf("%d", &n);
  33.     for (int i = n; i; --i)
  34.         scanf("%d", &a[i]);
  35.     copy(a + 1, a + n + 1, sorted);
  36.     sort(sorted + 1, sorted + n + 1);
  37.     for (int i = 1; i <= n; ++i)
  38.         a[i] = rk[i] = lower_bound(sorted + 1, sorted + n + 1, a[i]) - sorted;
  39.     for (int l = 1; l <= n; l <<= 1) {
  40.         memset(cnt, 0, sizeof(cnt));
  41.         for (int i = 1; i <= n; ++i) {
  42.             p[i].id = i;
  43.             p[i].a = rk[i];
  44.             p[i].b = (i + l) > n ? 0 : rk[i + l];
  45.             ++cnt[p[i].b];
  46.         }
  47.         for (int i = 1; i <= n; ++i)
  48.             cnt[i] += cnt[i - 1];
  49.         for (int i = n; i; --i)
  50.             q[cnt[p[i].b]--] = p[i];
  51.         memset(cnt, 0, sizeof(cnt));
  52.         for (int i = 1; i <= n; ++i)
  53.             ++cnt[q[i].a];
  54.         for (int i = 1; i <= n; ++i)
  55.             cnt[i] += cnt[i - 1];
  56.         for (int i = n; i; --i)
  57.             p[cnt[q[i].a]--] = q[i];
  58.         for (int i = 1; i <= n; ++i) {
  59.             rk[p[i].id] = rk[p[i - 1].id];
  60.             if (p[i].a != p[i - 1].a || p[i].b != p[i - 1].b)
  61.                 ++rk[p[i].id];
  62.         }
  63.     }
  64.     for (int i = 1; i <= n; ++i)
  65.         sa[rk[i]] = i;
  66.     for (int i = 1; i <= n; ++i) {
  67.         h[i] = h[i - 1] - 1;
  68.         if (h[i] < 0)
  69.             h[i] = 0;
  70.         while (a[i + h[i]] == a[sa[rk[i] - 1] + h[i]])
  71.             ++h[i];
  72.     }
  73.     for (int i = 1; i <= n; ++i)
  74.         height[rk[i]] = h[i];
  75.     node* seg = build(1, n);
  76.     set<int> st;
  77.     for (int i = n; i; --i) {
  78.         set_t::iterator iter = st.insert(rk[i]).first, pre = iter, pst = iter;
  79.         if (iter != st.begin()) {
  80.             --pre;
  81.             hsum += seg->query(*pre + 1, rk[i]);
  82.             if (++pst != st.end()) {
  83.                 hsum += seg->query(rk[i] + 1, *pst);
  84.                 hsum -= seg->query(*pre + 1, *pst);
  85.             }
  86.         } else if (++pst != st.end())
  87.             hsum += seg->query(rk[i] + 1, *pst);
  88.         printf("%lld\n", (ll)(n - i + 1) * (n - i + 2) / 2 - hsum);
  89.     }
  90.     return 0;
  91. }
  92.  
  93. node* build(int l, int r) {
  94.     static node pool[N * 2];
  95.     static node* top = pool;
  96.     node* p = top;
  97.     ++top;
  98.     p->l = l;
  99.     p->r = r;
  100.     if (l == r) {
  101.         p->d = height[l];
  102.         return p;
  103.     }
  104.     int mid = (l + r) / 2;
  105.     p->ls = build(l, mid);
  106.     p->rs = build(mid + 1, r);
  107.     p->d = min(p->ls->d, p->rs->d);
  108.     return p;
  109. }
  110.  
  111. int node::query(int l, int r) const {
  112.     if (this->l == l && this->r == r)
  113.         return d;
  114.     if (r <= ls->r)
  115.         return ls->query(l, r);
  116.     if (l >= rs->l)
  117.         return rs->query(l, r);
  118.     return min(ls->query(l, ls->r), rs->query(rs->l, r));
  119. }
Advertisement
Add Comment
Please, Sign In to add comment