多校#5-1005-Instring-HDU5785-manacher+维护
寻找三元组(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+维护的更多相关文章
- HDU5785 manacher+差分数组
用manacher算法O(n)求出所有的回文半径.有了回文半径后,就可以求出L[i]表示以i结尾的回文串的起始位置的和R[i]表示以i起始的回文串的结尾位置的和,然后就可以求出答案了,这里要注意奇偶长 ...
- 2019湘潭校赛 E(答案区间维护)
题目传送 思路是始终维护西瓜数量的区间,即L代表目前可以达到的最少的,R是最多的,然后判断一下. #include <bits/stdc++.h> using namespace std; ...
- HDU 4690 EBCDIC (2013多校 1005题 胡搞题)
EBCDIC Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)Total Su ...
- HDU 6695 Welcome Party (贪心)
2019 杭电多校 10 1005 题目链接:HDU 6695 比赛链接:2019 Multi-University Training Contest 10 Problem Description T ...
- HDU 6628 permutation 1 (暴力)
2019 杭电多校 5 1005 题目链接:HDU 6628 比赛链接:2019 Multi-University Training Contest 5 Problem Description A s ...
- 扩展kmp 学习笔记
学习了一下这个较为冷门的知识,由于从日报开始看起,还是比较绕的-- 首先定义 \(Z\) 函数表示后缀 \(i\) 与整个串的 \(lcp\) 长度 一个比较好的理解于实现方式是类似于 \(manac ...
- 后缀自动机(SAM)+广义后缀自动机(GSA)
经过一顿操作之后竟然疑似没退役0 0 你是XCPC选手吗?我觉得我是! 稍微补一点之前丢给队友的知识吧,除了数论以外都可以看看,为Dhaka和新队伍做点准备... 不错的零基础教程见 IO WIKI ...
- 多校1005 HDU5785 Interesting (manacher)
// 多校1005 HDU5785 Interesting // 题意:给你一个串,求相邻两个回文串左边端点*右边端点的和 // 思路:马拉车算出最长回文半径,求一个前缀和,既得到每个点对答案的贡献. ...
- HDU 5371 (2015多校联合训练赛第七场1003)Hotaru's problem(manacher+二分/枚举)
pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序 ...
随机推荐
- 一篇 SpringData+JPA 总结
概述 SpringData,Spring 的一个子项目,用于简化数据库访问,支持 NoSQL 和关系数据库存储 SpringData 项目所支持 NoSQL 存储 MongDB(文档数据库) Neo4 ...
- Unique Snowflakes UVA - 11572 (离散化+尺取法)
Emily the entrepreneur has a cool business idea: packaging and selling snowflakes. She has devised a ...
- vue: WebStorm设置快速编译运行
WebSorm是一款优秀的前端开发工具,而Vue项目可以使用Node进行编译运行,平常我们可以通过命令行部署项目进行调试. 本文介绍设置Webstorm进行快速部署Vue项目. 第一步 点击启动快捷按 ...
- Navicat还原出现Finished - Stopped before completion的问题
查看数据库中最大的单个文件容量 SHOW VARIABLES LIKE '%max_allowed_packet%'; 设置最大单个文件容量为10M,单次有效(新建查询---运行) SET GLO ...
- pinpoint vs druid
主流Java数据库连接池分析(C3P0,DBCP,TomcatPool,BoneCP,Druid) - ppjj - 博客园 https://www.cnblogs.com/nizuimeiabc1/ ...
- symfony框架
Symfony是一个完整的框架结构,设计用来帮助并加速网络应用的开发. 1)安装 symfony的安装还是比较简单的,而且提供了多种安装的方式,详情可以看官网手册 问题: cURL error 60: ...
- 通过arcmap发布缓存服务,无法选择自定义方案
出现该问题是因为缓存目录有该缓存信息,清楚掉之后就可以选择自定义方案了
- 11 The superlative
1 最高级用来表明三个或更多事物之间的关系.最高级是通过在形容词之前加 "the" 并在之后加 "-est",或在形容词之前加 "the most&q ...
- linux 安装 SVN server
安装 使用yum安装非常简单: yum install subversion 配置 2.1. 创建仓库 我们这里在/home下建立一个名为svn的仓库(repository),以后所有代码都放在这个下 ...
- Prime Permutation
Prime Permutation 原题地址: http://codeforces.com/problemset/problem/123/A 题目大意: 给你一个字符串(只包含小写字母),从1开始存放 ...