寻找三元组(i,j,k),使得(i,j)(j,k)都是回文字串,其中i<=j<k.

可以发现,对于每一位i,只要预处理出来有多少个以i为右端的回文串和以i为左端的回文串。把那些串的另一端的坐标和计算出来就可以了。

然后ans = ∑cntR[i]*cntL[i+1]

这里cntR[i]记录以i为右端的回文串的左端坐标和。cntL[i]同理。

然后这道题的数据范围是1e6,多case。必须要O(n)才能过。

首先用O(n)的Manacher处理每一位的回文半径,之后遍历处理

可以发现这里需要O(n)复杂度给指定区间加上一个等差序列。于是开几个数组维护,空间换时间。

用cnt_add记录加了多少次,add记录首项加了多少,这样从首项往后递推,每次add[i+1] = add[i]-cnt_add[i] cnt_add[i+1] += cnt_add[i] cntL[i] += add[i]

这样可以从首项更新到字符串尾。但是我们要更新一段值,就有一段多加了,于是就再开一个mns记录多加的的值.

比如要更新[l,r] 那么就给mns[r+1]置为add[r+1]时的值。这样就可以把多加的抵消了。同时也要维护一个cnt_mns记录次数。

最后还要注意分回文长度奇偶讨论。

//坑了好久的题。最开始想到了用树状数组维护cnt,成段更新,然而卡log。

 #include <cstdio>
#include <ctype.h>
#include <cstring>
#include <algorithm> #define LL long long
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define root 1,N,1
using namespace std; const int maxn = 1e6+;
const LL MOD = 1e9+; char Ma[*maxn];
int Mp[*maxn];
void update(LL &x,LL d)
{
x += d;
if(x >= MOD) x -= MOD;
if(x < ) x += MOD;
} void Manacher(char s[],int len)
{
memset(Mp,,sizeof Mp);
int l = ;
Ma[l++] = '$';
Ma[l++] = '#';
for(int i=;i<len;i++)
{
Ma[l++] = s[i];
Ma[l++] = '#';
}
Ma[l] = ;
int mx = ,id = ;
for(int i=;i<l;i++)
{
Mp[i] = mx > i ? min(Mp[*id-i],mx-i) : ;
while(Ma[i+Mp[i]] == Ma[i-Mp[i]] ) Mp[i]++;
if(i + Mp[i] > mx)
{
mx = i+Mp[i];
id = i;
}
}
} char line[maxn];
int p[maxn];
LL cntL[maxn],cntR[maxn];
LL add[maxn],mns[maxn];
LL cnt_add[maxn],cnt_mns[maxn]; void init()
{
memset(cnt_mns,,sizeof cnt_mns);
memset(cnt_add,,sizeof cnt_add);
memset(add,,sizeof add);
memset(mns,,sizeof mns);
} LL ans = ;
void solve(int len)
{
init();
for(int i=;i<*len+;i++)
{
int tmp = Mp[i];
if(Ma[i] == '#')
{
int cur = i/+,L = (i-tmp)/+, R = (i+tmp)/-,r = (tmp-)/;
update(add[L],R);
update(mns[cur],R-r);
cnt_add[L] ++;
cnt_mns[cur]++;
}else
{
int cur = i/,L = (i-tmp)/+, R = (i+tmp)/-,r = +(tmp-)/;
update(add[L],R);
update(mns[cur+],R-r);
cnt_add[L] ++;
cnt_mns[cur+]++;
}
}
for(int i=;i<=len;i++)
{
update(cntL[i],add[i]-mns[i]);
update(add[i+],add[i]-cnt_add[i]);
update(mns[i+],mns[i]-cnt_mns[i]);
update(cnt_add[i+],cnt_add[i]);
update(cnt_mns[i+],cnt_mns[i]);
} init();
for(int i=;i<*len+;i++)
{
int tmp = Mp[i];
if(Ma[i] == '#')
{
int cur = i/+,L = (i-tmp)/+, R = (i+tmp)/-,r = (tmp-)/;
add[cur] += cur-;
mns[R+] += cur - r - ;
cnt_add[cur] ++;
cnt_mns[R+] ++;
}else
{
int cur = i/,L = (i-tmp)/+, R = (i+tmp)/-,r = +(tmp-)/;
add[cur] += cur;
mns[R+] += cur-r;
cnt_add[cur] ++;
cnt_mns[R+] ++;
}
}
for(int i=;i<=len;i++)
{
update(cntR[i],add[i]-mns[i]);
update(add[i+],add[i]-cnt_add[i]);
update(mns[i+],mns[i]-cnt_mns[i]);
update(cnt_add[i+],cnt_add[i]);
update(cnt_mns[i+],cnt_mns[i]);
}
ans = ;
for(int i=;i<=len;i++)
{
update(ans,(cntR[i]*cntL[i+])%MOD);
}
} int main()
{
//freopen("1005.in","r",stdin);
while(true)
{
char c;
int len = ;
while((c = getchar()) && isalpha(c))
{
line[len++] = c;
}
if(c == EOF) break;
Manacher(line,len); memset(cntL,,sizeof cntL);
memset(cntR,,sizeof cntR);
solve(len);
printf("%I64d\n",(ans+MOD) % MOD);
}
}

多校#5-1005-Instring-HDU5785-manacher+维护的更多相关文章

  1. HDU5785 manacher+差分数组

    用manacher算法O(n)求出所有的回文半径.有了回文半径后,就可以求出L[i]表示以i结尾的回文串的起始位置的和R[i]表示以i起始的回文串的结尾位置的和,然后就可以求出答案了,这里要注意奇偶长 ...

  2. 2019湘潭校赛 E(答案区间维护)

    题目传送 思路是始终维护西瓜数量的区间,即L代表目前可以达到的最少的,R是最多的,然后判断一下. #include <bits/stdc++.h> using namespace std; ...

  3. HDU 4690 EBCDIC (2013多校 1005题 胡搞题)

    EBCDIC Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)Total Su ...

  4. HDU 6695 Welcome Party (贪心)

    2019 杭电多校 10 1005 题目链接:HDU 6695 比赛链接:2019 Multi-University Training Contest 10 Problem Description T ...

  5. HDU 6628 permutation 1 (暴力)

    2019 杭电多校 5 1005 题目链接:HDU 6628 比赛链接:2019 Multi-University Training Contest 5 Problem Description A s ...

  6. 扩展kmp 学习笔记

    学习了一下这个较为冷门的知识,由于从日报开始看起,还是比较绕的-- 首先定义 \(Z\) 函数表示后缀 \(i\) 与整个串的 \(lcp\) 长度 一个比较好的理解于实现方式是类似于 \(manac ...

  7. 后缀自动机(SAM)+广义后缀自动机(GSA)

    经过一顿操作之后竟然疑似没退役0 0 你是XCPC选手吗?我觉得我是! 稍微补一点之前丢给队友的知识吧,除了数论以外都可以看看,为Dhaka和新队伍做点准备... 不错的零基础教程见 IO WIKI ...

  8. 多校1005 HDU5785 Interesting (manacher)

    // 多校1005 HDU5785 Interesting // 题意:给你一个串,求相邻两个回文串左边端点*右边端点的和 // 思路:马拉车算出最长回文半径,求一个前缀和,既得到每个点对答案的贡献. ...

  9. HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

    pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序 ...

随机推荐

  1. IIS配置Url重写实现http自动跳转https的重定向方法(100%解决)

    引言 本文推荐阅读地址:https://www.52abp.com/BlogDetails/10008 这种文章网上可以说一搜一大把,但是我为什么还要写呢,因为一搜一把没把我气死,都是东抄西挪的东西, ...

  2. 关于VS2017 添加 EF的MVC控制器报错的解决方法

    1. 错误描述 :no database provider has been configured fot this DbContext. 此类错误是上下文的注册造成的.解决方式在DBContext中 ...

  3. H5 id选择器

    09-id选择器 迟到毁一生 早退穷三代 按时上下班 必成高富帅 <!DOCTYPE html> <html lang="en"> <head> ...

  4. 【评分】Alpha 事后诸葛亮(团队)

    [评分]Alpha 事后诸葛亮(团队) 总结 按时交 - 有分 晚交 - 0分 迟交一周以上 - 倒扣本次作业分数 抄袭 - 倒扣本次作业分数 本次作业都是以问答形式进行,大部分同学在回答问题方面都一 ...

  5. python的四种内置数据结构

    对于每种编程语言一般都会规定一些容器来保存某些数据,就像java的集合和数组一样python也同样有这样的结构 而对于python他有四个这样的内置容器来存储数据,他们都是python语言的一部分可以 ...

  6. jmeter压测参数设定(转)

    jmeter压测参数设定 一.基本公式 线程数 = QPS * time: 注:QPS--每秒完成请求的个数:time--每个请求响应完成平均需要时间: 故QPS * time就是所有请求完成响应所需 ...

  7. Json详解以及fastjson使用教程

    Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言.在使用Java做Web开发时,不可避免的会遇到Json的使 ...

  8. linux重装后配一些库

    #先要设置软件源 sudo apt-get update sudo apt-get upgrade #播放器 sudo apt-get install smplayer qt sudo apt-get ...

  9. 运行Spark-shell,解决Unable to load native-hadoop library for your platform

    启动spark后,运行bin/spark-shell会出现一个警告 提君博客原创 WARN util.NativeCodeLoader: Unable to load native-hadoop li ...

  10. k8s HPA自动收缩

    HPA自动收缩 autoscale 自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量 #创建一个replicaset测试 [r ...