HDU5371——Manacher+set维护——Hotaru's problem

http://acm.hdu.edu.cn/showproblem.php?pid=5371

/*
先用Manacher算法得出最长回文子串,然后用set维护ans的值
对所有回文的长度进行排序, 那么之后的点如果覆盖了最接近的点那么那么点肯定是覆盖了当前点,用二分得到最近不大于u的距离
S.upper_bound(id+u) 从起始到末尾得到第一个大于id+u的迭代器,
S.lower_bound(id-u) 从起始到末尾得到第一个不小于id-u的迭代器
set 容器自动从小到大排序
*/
/************************************************
* Author        :Powatr
* Created Time  :2015-8-12 19:49:44
* File Name     :1003.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 4e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

int n;
int p[MAXN];
int len;
int a[MAXN];
int aa[MAXN];
set<int> S;
set<int>::iterator it;
struct edge{
    int u, id;
}b[MAXN];
bool cmp(edge i, edge j)
{
    return i.u > j.u;
}
void inti()
{
    memset(p, 0, sizeof(p));
    memset(aa, -1, sizeof(aa));
    for(int i = 1; i <= n; i++)
        aa[i*2] = a[i];
    len = n*2 + 1;
}

int read()
{
    char z = getchar();
    while(z < ‘0‘ || z > ‘9‘) z = getchar();
    int ans = 0;
    while( z >= ‘0‘ && z <= ‘9‘){
        ans = ans*10 + z - ‘0‘;
        z = getchar();
    }
    return ans;
}
void Manacher()
{
    int mx = 0;
    int id;
    for(int i = 1; i <= len; i++){
        if(mx > i){
            p[i] = min(p[2*id-i], mx - i);
        }
        else p[i] = 1;
        for( ;aa[i+p[i]] == aa[i-p[i]]; p[i]++);
        if(p[i] + i > mx){
            mx = p[i] + i;
            id = i;
        }
    }
}

int main(){
   int T;
   scanf("%d", &T);
   for(int cas = 1; cas <= T; cas++){
       S.clear();
       n = read();
       for(int i = 1; i <= n; i++)
           a[i] = read();
       inti();
       Manacher();
       for(int i = 1; i <= n; i++){
           b[i].u = (p[i*2+1]-1)/2;
           b[i].id = i;
       }
       sort(b+1, b+n+1, cmp);
       int ans = 0;
       for(int i = 1; i <= n; i++){
           int id = b[i].id;
           int u = b[i].u;
           if(u == 0) break;
           S.insert(id);
           it = S.upper_bound(id+u);
           it--;
           ans = max(ans, *it - id);
           it = S.lower_bound(id-u);
           ans = max(ans, id - *it);
       }
       printf("Case #%d: ", cas);
       printf("%d\n", 3*ans);
   }
   return 0;
}

  

HDU5371——Manacher+set维护——Hotaru's problem

时间: 2024-10-13 01:25:37

HDU5371——Manacher+set维护——Hotaru's problem的相关文章

Hotaru&amp;#39;s problem(hdu5371+Manacher)多校7

Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2274    Accepted Submission(s): 795 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playin

hdu5371 Hotaru&#39;s problem(manacher 算法+枚举)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371 题目大意:给一串数字,在子串中找到"1-2-1"的形式,其中1和2 是回文串,找出最长的那一串. 思路:利用manacher算法得出最长序列.观察子串形式,1和2是回文串,其实2和后面那个1也是回文串. 在之前我们已经通过manacher算法得到了每个数字所能延伸的长度,所以我们只要枚举第二段到第三段的距离即可. 当遇到第i个数字时,那么第二段和第三段的距离就是i+p[i],令j=i

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

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

HDU 5371 Hotaru&#39;s problem manacher+(线段树or set)

题意,给定一个100000 的串,求他一个子串,使得将子串分成三部分有后,第一部分=第三部分,第一部分与第二部分对称(回文) 首先我们需要处理出以i为轴的回文串的两端,这个事情可以用Manacher算法完成,复杂度O(n) http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ 这个博客写的很好懂.不会的童鞋可以去学习一下这个算法,非常精妙. 好的现在我们已经会了这个算法,并获得了每个点为轴的串的右端点p[i] 很简单地可以处理出左端

[2015hdu多校联赛补题]hdu5371 Hotaru&#39;s problem

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371 题意:把一个数字串A翻过来(abc翻过来为cba)的操作为-A,我们称A-AA这样的串为N-sequence,现在给你一个数字串,问你这个串中最长的N-sequence子串长度 解:可以想到A-A是一个回文串,-AA也是一个回文串,那么首先Manacher跑一遍求出所有回文子串 可以想到任意两个互相覆盖的回文子串都可以表示成N-sequence 然后有三种搞法: 1.时间复杂度O(N*logN

HDU 5371 Manacher Hotaru&#39;s problem

求出一个连续子序列,这个子序列由三部分ABC构成,其中AB是回文串,A和C相同,也就是BC也是回文串. 求这样一个最长的子序列. Manacher算法是在所有两个相邻数字之间插入一个特殊的数字,比如-1, Manacher算法跑完之后,就计算出每个数字为中心的回文子序列的最大长度 由题意可以知道,AB和BC必然是长度为偶数的回文串.所以我们枚举回文串的中心就枚举相邻两个数字之间的缝隙,也就是那些-1 把AB中间的间隙叫做左中心i,BC之间的间隙叫做右中心j,那么如果两个中心的范围能够互相覆盖,那

hdu 5371 Hotaru&#39;s problem(manacher+尺取法)

题意: 给定一个有n个数字的序列,找出一个连续的子序列满足这样的条件: 1. 平均分成三段 2. 第一段与第三段一样 3. 第二段是第一段的倒序.求这样的子序列的最大长度. 数据范围:n~100000 解析: 我看网络上面很多的题解都是用O(n2/32)的做法水数据过去的,这种做法是先用mancher算法预处理出每个每个回文串最远所能抵达的位置,然后枚举每个位置i,再枚举其回文串的长度,然后枚举当前位置i到回文串所能抵达的最远距离,判断途径的位置j是,否有回文串能够到当前位置i.但是这种做法的复

HDOJ 5371 Hotaru&#39;s problem manacher+优先队列+二分

先用求回文串的Manacher算法,求出以第i个点和第i+1个点为中心的回文串长度,记录到数组c中 比如 10 9 8 8 9 10 10 9 8 我们通过运行Manacher求出第i个点和第i+1个点为中心的回文串长度 0 0 6 0 0 6 0 0 0 两个8为中心,10 9 8 8 9 10是个回文串,长度是6. 两个10为中心,8 9 10 10 9 8是个回文串,长度是6. 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,比如上边的两个字符串,共享 8 9 10这一

HDU 5371 Hotaru&#39;s problem (Manacher,回文串)

题意:给一个序列,找出1个连续子序列,将其平分成前,中,后等长的3段子序列,要求[前]和[中]是回文,[中]和[后]是回文.求3段最长为多少?由于平分的关系,所以答案应该是3的倍数. 思路:先Manacher求最长子串,利用期间所记录的P 数组,穷举一下所有可能的前两串,再用O(1)时间判断第3串是否符合要求. 具体做法: (1)P[i]记录的是以i为中心,从i-P[i]+1到i+P[i]-1这段都是回文.由于前两段之和必为偶数,所以必须选取str[i]为'#'的. (2)扫一遍每个'#',以其