多校#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)的序 ...
随机推荐
- JS判断当前设备是 PC IOS Andriod
JS判断当前设备是 PC IOS Andriod <script > window.onload = function(){ var isPc = IsPC(); var isAndroi ...
- elasticsearch简单操作(二)
让我们建立一个员工目录,假设我们刚好在Megacorp工作,这时人力资源部门出于某种目的需要让我们创建一个员工目录,这个目录用于促进人文关怀和用于实时协同工作,所以它有以下不同的需求:1.数据能够包含 ...
- 接口自动化框架(Pytest+request+Allure)
前言: 接口自动化是指模拟程序接口层面的自动化,由于接口不易变更,维护成本更小,所以深受各大公司的喜爱. 接口自动化包含2个部分,功能性的接口自动化测试和并发接口自动化测试. 本次文章着重介绍第一种, ...
- c++ 入门之深入探讨拷贝函数和内存分配
在c++入门之深入探讨类的一些行为时,说明了拷贝函数即复制构造函数运用于如下场景: 对象作为函数的参数,以值传递的方式传给函数. 对象作为函数的返回值,以值的方式从函数返回 使用一个对象给另一个对象初 ...
- 用PhoneGap创建第一个项目
1.在eclipse中新建Android Project2.在项目的目录下,建两个文件夹:/libs/assets/www3.进入将刚刚下载并解压的PhoneGap包里Anroid目录,我们需要的资源 ...
- 【学习总结】C-翁恺老师-入门-总
2019-1-2 翁恺老师C入门视频-启程 代码详见GitHub: 目录 第0周:程序设计与C语言 第1周:计算 第2周:判断 第3周:循环 第4周:循环控制 第5周:数据类型 第6周:函数 第7周: ...
- 【问题解决方案】之 关于某江加密视频swf专用播放器仍无法播放的问题
前言: 从pt上下载了一些语言学习的视频之后一直打不开,百度谷歌了若干种方法仍然无解.无奈放弃. 某日从百度知道里又看到一个方法,试了一下,居然灵了.呜呼哀哉.赶紧记下来. 原方法链接:https:/ ...
- SQLServer数据库分页
以 项目表 PM_Project 为例. PM_Project 全部内容如下(共6条数据): 一.Top – Not In - Top 方式分页 直接的,原始的,不采用函数,纯手动挡. 分步探索过 ...
- C# Note17: 使用Ionic.Zip.dll实现解压缩文件
首先下载ionic.Zip.dll,然后在项目中添加该引用,之后就可以在cs中使用了: using Ionic.Zip; #region Ionic.Zip压缩文件 private readonly ...
- 剑指Offer(9)
题目: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 解法: 要考虑到底数为0,指数为负数的情况,这道题主要考的是对边界值的思考. p ...