多校#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。

  1 #include <cstdio>
  2 #include <ctype.h>
  3 #include <cstring>
  4 #include <algorithm>
  5
  6 #define LL long long
  7 #define lson rt<<1,l,mid
  8 #define rson rt<<1|1,mid+1,r
  9 #define root 1,N,1
 10 using namespace std;
 11
 12 const int maxn = 1e6+100;
 13 const LL MOD = 1e9+7;
 14
 15 char Ma[2*maxn];
 16 int Mp[2*maxn];
 17 void update(LL &x,LL d)
 18 {
 19     x += d;
 20     if(x >= MOD) x -= MOD;
 21     if(x < 0) x += MOD;
 22 }
 23
 24 void Manacher(char s[],int len)
 25 {
 26     memset(Mp,0,sizeof Mp);
 27     int l = 0;
 28     Ma[l++] = ‘$‘;
 29     Ma[l++] = ‘#‘;
 30     for(int i=0;i<len;i++)
 31     {
 32         Ma[l++] = s[i];
 33         Ma[l++] = ‘#‘;
 34     }
 35     Ma[l] = 0;
 36     int mx = 0,id = 0;
 37     for(int i=0;i<l;i++)
 38     {
 39         Mp[i] = mx > i ? min(Mp[2*id-i],mx-i) : 1;
 40         while(Ma[i+Mp[i]] == Ma[i-Mp[i]] ) Mp[i]++;
 41         if(i + Mp[i] > mx)
 42         {
 43             mx = i+Mp[i];
 44             id = i;
 45         }
 46     }
 47 }
 48
 49 char line[maxn];
 50 int p[maxn];
 51 LL cntL[maxn],cntR[maxn];
 52 LL add[maxn],mns[maxn];
 53 LL cnt_add[maxn],cnt_mns[maxn];
 54
 55 void init()
 56 {
 57     memset(cnt_mns,0,sizeof cnt_mns);
 58     memset(cnt_add,0,sizeof cnt_add);
 59     memset(add,0,sizeof add);
 60     memset(mns,0,sizeof mns);
 61 }
 62
 63 LL ans = 0;
 64 void solve(int len)
 65 {
 66     init();
 67     for(int i=2;i<2*len+1;i++)
 68     {
 69         int tmp = Mp[i];
 70         if(Ma[i] == ‘#‘)
 71         {
 72             int cur = i/2+1,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = (tmp-1)/2;
 73             update(add[L],R);
 74             update(mns[cur],R-r);
 75             cnt_add[L] ++;
 76             cnt_mns[cur]++;
 77         }else
 78         {
 79             int cur = i/2,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = 1+(tmp-1)/2;
 80             update(add[L],R);
 81             update(mns[cur+1],R-r);
 82             cnt_add[L] ++;
 83             cnt_mns[cur+1]++;
 84         }
 85     }
 86     for(int i=1;i<=len;i++)
 87     {
 88         update(cntL[i],add[i]-mns[i]);
 89         update(add[i+1],add[i]-cnt_add[i]);
 90         update(mns[i+1],mns[i]-cnt_mns[i]);
 91         update(cnt_add[i+1],cnt_add[i]);
 92         update(cnt_mns[i+1],cnt_mns[i]);
 93     }
 94
 95     init();
 96     for(int i=2;i<2*len+1;i++)
 97     {
 98         int tmp = Mp[i];
 99         if(Ma[i] == ‘#‘)
100         {
101             int cur = i/2+1,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = (tmp-1)/2;
102             add[cur] += cur-1;
103             mns[R+1] += cur - r - 1;
104             cnt_add[cur] ++;
105             cnt_mns[R+1] ++;
106         }else
107         {
108             int cur = i/2,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = 1+(tmp-1)/2;
109             add[cur] += cur;
110             mns[R+1] += cur-r;
111             cnt_add[cur] ++;
112             cnt_mns[R+1] ++;
113         }
114     }
115     for(int i=1;i<=len;i++)
116     {
117         update(cntR[i],add[i]-mns[i]);
118         update(add[i+1],add[i]-cnt_add[i]);
119         update(mns[i+1],mns[i]-cnt_mns[i]);
120         update(cnt_add[i+1],cnt_add[i]);
121         update(cnt_mns[i+1],cnt_mns[i]);
122     }
123     ans = 0;
124     for(int i=1;i<=len;i++)
125     {
126         update(ans,(cntR[i]*cntL[i+1])%MOD);
127     }
128 }
129
130 int main()
131 {
132     //freopen("1005.in","r",stdin);
133     while(true)
134     {
135         char c;
136         int len = 0;
137         while((c = getchar()) && isalpha(c))
138         {
139             line[len++] = c;
140         }
141         if(c == EOF) break;
142         Manacher(line,len);
143
144         memset(cntL,0,sizeof cntL);
145         memset(cntR,0,sizeof cntR);
146         solve(len);
147         printf("%I64d\n",(ans+MOD) % MOD);
148     }
149 }
时间: 2024-10-13 01:35:04

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

HDU 4975 (杭电多校 #10 1005题)A simple Gaussian elimination problem.(网络流之最大流)

题目地址:HDU 4975 对这题简直无语...本来以为这题要用什么更先进的方法,结果还是老方法,这么卡时间真的好吗....比赛的时候用了判环的方法,一直TLE..后来换了矩阵DP的方式,加了加剪枝就过了..无语了.. 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cstdio> #include <

2015 多校 #5 1005 MZL&#39;s chemistry

MZL's chemistry Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1306    Accepted Submission(s): 601 Problem Description MZL define F(X) as the first ionization energy of the chemical element X N

HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列,该子序列分为三部分,第一部分与第三部分相同,第一部分与第二部分对称,如果存在求最长的符合这种条件的序列. 思路:用Manacher算法来处理回文串的长度,记录下以每一个-1(Manacher算法的插入)为中心的最大回文串的长度.然后从最大的开始穷举,只要p[i]-1即能得出以数字为中心的最大回文串的长度,然后找到右边对应的'-1',判断p[i]是不是大于所穷举的长度,如果当前的满足三段,那么就跳出,继续

HDU5785 manacher+差分数组

用manacher算法O(n)求出所有的回文半径.有了回文半径后,就可以求出L[i]表示以i结尾的回文串的起始位置的和R[i]表示以i起始的回文串的结尾位置的和,然后就可以求出答案了,这里要注意奇偶长度回文串的不同处理.复杂度O(n) 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1e6+10; 4 typedef long long ll; 5 const int mod = 1e9+7; 6 int n,m

计算几何学习12 + 组队训练

学习了极角排序的一些套路 UVA11696 给你一些圆和一些点,保证点不在圆内,两点相连通当且仅当两点联结的线段不与任何一个圆相交,问联通块个数 跟之前那道UVA很类似 其实更加简单 枚举每个点 把其他所有点和圆对他极角排序 用set维护圆到当前点的切线的最短距离 因为点不在圆内 所以直接判断距离就行了 poj 2280 给你一些A类点 B类点 寻找一条直线 使得线上的点和直线左侧的A类点 直线右侧的B类点数目之和最大 首先可以知道直线一定从 给定两点的连线中产生 所以考虑枚举点 让其他点对他极

HDU 6695 Welcome Party (贪心)

2019 杭电多校 10 1005 题目链接:HDU 6695 比赛链接:2019 Multi-University Training Contest 10 Problem Description The annual welcome party of the Department of Computer Science and Technology is coming soon! Many students have been applying to show up at the welcom

数字化校园建设方案

第一章 总体目标 1.1 总体目标 建设一个运行于统一平台.统一技术框架下的学校门户系统.管理信息系统和教学资源管理系统及应用平台. 根据国示范建设中有关数字化校园建设的要求及我校实际情况,采用走出去请进来,遵循面向服务架构(SOA)的设计原则进行系统的需求分析.总体设计,实现技术先进.高效稳定.安全可靠.信息规范.数据完整的一体化数字化校园系统.消除信息孤岛和应用孤岛:支持师生教学与学习:支持学校决策和管理:支持数据信息共建共享:为学校师生提供一站式管理服务:提高工作效率,提高管理效率,提高决

网络运维第1章

OSI七层网络参考模型应用层-------------服务于最终用户计算机的一个接口表示层------------数据的表示,加密,安全等会话层------------建立会话,管理断开会话传输层-----------定义数据传输的协议,端口.以及流量控制和差验校错网络层-----------逻辑地址寻址,实现到达不同目标地址的路径选择数据链路层-----建立逻辑连接,物理地址寻址.差验校错物理层------------建立物理连接,维护,断开物理连接 TCP/IP网络参考模型Tcp五层模型 t

多校1005 HDU5785 Interesting (manacher)

1 // 多校1005 HDU5785 Interesting 2 // 题意:给你一个串,求相邻两个回文串左边端点*右边端点的和 3 // 思路:马拉车算出最长回文半径,求一个前缀和,既得到每个点对答案的贡献. 4 // ans=L[i]*R[i-1] 5 // L[i] 以i开始的所有回文串结尾坐标的和 6 // R[i] 以i结尾的所有回文串开始坐标的和 7 // 这题我们关键是求L[] R[] 8 // 另开两个数组a[] b[] 分别记录当前点对答案贡献 和每个点出现的次数 9 10

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

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以