HDU 5371 Hotaru's problem

利用Manacher求出每两个数字中间位置的回文长度

之后利用set进行维护,大题思路如下:

要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,比如上边的两个字符串,共享 8 9 10这一部分。 也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样。 因为我们已经记录下来以第i个点和第i+1个点为中心的回文串长度, 那么问题可以转化成,相距x的两个数a[i],a[i+x],满足a[i]/2>=x 并且 a[i+x]/2>=x,要求x尽量大

这可以用一个set维护,一开始集合为空,依次取出a数组中最大的元素,将其下标放入set中,每取出一个元素,再该集合中二分查找比i+a[i]/2小,但最大的元素,更新答案。 然后查找集合中比i-a[i]/2大,但最小的元素,更新答案。

但是据说数据比较水,所以可以用可能退化成 O(n2) 的枚举方法也可以过。

参考官方题解:http://bestcoder.hdu.edu.cn/blog/

// whn6325689
// Mr.Phoebe
// http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62
#define speed std::ios::sync_with_stdio(false);

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;

#define CLR(x,y) memset(x,y,sizeof(x))
#define CPY(x,y) memcpy(x,y,sizeof(x))
#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))
#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))

#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))

#define MID(x,y) (x+((y-x)>>1))
#define ls (idx<<1)
#define rs (idx<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
#define root 1,1,n

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1;
    char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------

const int MAXN=200010;

int num[MAXN],dst[MAXN];
int n,len[MAXN];
set<int> st;
pii pos[MAXN];
void Manacher(int *s)
{
    int l=0;
    dst[l++]=-2;dst[l++]=-1;
    for(int i=0;i<n;i++)
    {
        dst[l++]=s[i];
        dst[l++]=-1;
    }
    int mx=0,po=0;
    for(int i=0;i<l;i++)
    {
        len[i]=mx>i?min(mx-i,len[2*po-i]):1;
        while(dst[i-len[i]]==dst[i+len[i]])
            len[i]++;
        if(len[i]+i>mx)
        {
            mx=len[i]+i;
            po=i;
        }
    }
}

int main()
{
    freopen("data.txt","r",stdin);
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        st.clear();CLR(len,0);
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&num[i]);
        Manacher(num);
        for(int i=0;i<n;i++)
        {
            pos[i]=mp((len[i*2+1]-1)/2,i);
        }
        sort(pos,pos+n);
        int ans=0;
        set<int>::iterator it,it1;
        for(int i=n-1;i>=0;i--)
        {
            st.insert(pos[i].second);
            it=(st.lower_bound(pos[i].second-pos[i].first));
            it1=(st.upper_bound(pos[i].second+pos[i].first));
            it1--;
            ans=max(ans,*it1-pos[i].second);
            ans=max(ans,pos[i].second-*it);
        }
        printf("Case #%d: %d\n",cas++,3*ans);
    }
    return 0;
}

枚举法

// whn6325689
// Mr.Phoebe
// http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62
#define speed std::ios::sync_with_stdio(false);

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;

#define CLR(x,y) memset(x,y,sizeof(x))
#define CPY(x,y) memcpy(x,y,sizeof(x))
#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))
#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))

#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))

#define MID(x,y) (x+((y-x)>>1))
#define ls (idx<<1)
#define rs (idx<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
#define root 1,1,n

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1;
    char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------


const int MAXN=100007;
int num[MAXN<<1];
int tmp[MAXN<<1];
int len[MAXN<<1];
int n;

void manacher(int *st,int *dst)
{
    int l=0;
    dst[l++]=-2;dst[l++]=-1;
    for(int i=0;i<n;i++)
    {
        dst[l++]=st[i];
        dst[l++]=-1;
    }
    int mx=0,po=0;
    for(int i=0;i<l;i++)
    {
        len[i]=mx>i?min(mx-i,len[2*po-i]):1;
        while(dst[i-len[i]]==dst[i+len[i]])
            len[i]++;
        if(len[i]+i>mx)
        {
            mx=len[i]+i;
            po=i;
        }
    }
}

int main ()
{
    freopen("data.txt","r",stdin);
    int T,cas=1;
    read(T);
    while(T--)
    {
        read(n);
        for(int i=0;i<n;i++)
            read(num[i]);
        manacher(num,tmp);
        int ans=0,l=2*n+1;
        for(int i=1;i<=l;i+=2)
            for(int j=i+len[i]-1;j-i>ans;j-=2)
                if(j-i+1<=len[j])
                {
                    ans=j-i;
                    break;
                }
        ans=ans/2*3;
        printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}

你可能感兴趣的:(HDU 5371 Hotaru's problem)