zoukankan      html  css  js  c++  java
  • CF17E Palisection

    嘟嘟嘟

    题中让求相交的回文串的对数,不太好求。不过求不相交的回文串对数就简单多了。

    因为对于一位 i,在这一位不相交的回文串对数numi = 以这一位结束的回文串个数 ×在这一位后面开始的回文串个数。用manacher跑一遍 + 差分,然后维护一个开始的回文串的后缀和就好了。

    然后统计回文串个数sum,那么ans = sum * (sum - 1) / 2 - ∑numi

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const int mod = 51123987;
    21 const int maxn = 2e6 + 5;
    22 inline ll read()
    23 {
    24     ll ans = 0;
    25     char ch = getchar(), last = ' ';
    26     while(!isdigit(ch)) {last = ch; ch = getchar();}
    27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    28     if(last == '-') ans = -ans;
    29     return ans;
    30 }
    31 inline void write(ll x)
    32 {
    33     if(x < 0) x = -x, putchar('-');
    34     if(x >= 10) write(x / 10);
    35     putchar(x % 10 + '0');
    36 }
    37 
    38 int n;
    39 char s[maxn], t[maxn << 1];
    40 int p[maxn << 1];
    41 int enn[maxn << 1], beg[maxn << 1];
    42 
    43 void init()
    44 {
    45   t[0] = '@';
    46   for(int i = 0; i < n; ++i) t[i << 1 | 1] = '#', t[(i << 1) + 2] = s[i];
    47   n = (n << 1) + 2;
    48   t[n - 1] = '#'; t[n] = '$';
    49 }
    50 void manacher()
    51 {
    52   int mx = 0, id;
    53   for(int i = 1; i < n; ++i)
    54     {
    55       if(mx > i) p[i] = min(p[(id << 1) - i], mx - i);
    56       else p[i] = 1;
    57       while(t[i - p[i]] == t[i + p[i]]) p[i]++;
    58       if(i + p[i] > mx) mx = p[i] + i, id = i;
    59     }
    60 }
    61 
    62 ll ans = 0;
    63 
    64 int main()
    65 {
    66   n = read();
    67   scanf("%s", s);
    68   init(); manacher();
    69   for(int i = 1; i <= n; ++i)
    70     {
    71       enn[i - p[i] + 1]++;
    72       enn[i + 1]--;
    73       beg[i]++;
    74       beg[i + p[i]]--;
    75       ans = (ans + (p[i] >> 1) % mod) % mod;
    76     }
    77   ans = (ans * (ans - 1) >> 1) % mod;
    78   for(int i = 1, sum = 0; i <= n; ++i)
    79     {
    80       enn[i] += enn[i - 1]; beg[i] += beg[i - 1];
    81       if(i % 2 == 0) ans = (ans - (ll)sum * (ll)enn[i] % mod + mod) % mod, sum = (sum + beg[i]) % mod;
    82     }
    83   write(ans), enter;
    84   return 0;
    85 }
    View Code
  • 相关阅读:
    一本通1331后缀表达式的值
    一本通1198 逆波兰表达式
    一本通1311 求逆序对(归并排序应用)
    快速排序
    一本通1310 车厢重组(冒泡排序,类似逆序对)
    一本通1186 出现次数超过一半的数(类似桶排序)
    一本通1216 红与黑 (代码没有参考任何博客,完全是自己写的,我搜索出山了!!!)
    一本通1222 放苹果
    一本通 1212 LETTERS
    一本通1215 迷宫
  • 原文地址:https://www.cnblogs.com/mrclr/p/9773530.html
Copyright © 2011-2022 走看看