• JZOJ 4366. 【GDKOI2016】项链


    ( ext{Problem})

    给出一个项链,删去连续的一部分,使剩下的对称,且长度最长

    ( ext{Analysis})

    可以发现,剩下的合法项链一定是由两个回文串接起来(由对称性质可知)
    先套路地将项链倍长
    那么我们只要用 ( ext{Manacher}) 算出以每个点中心的回文半径 (p[i])
    找到两个中心 (i,j(j > i)) 使得 (j - i le n)(i + p[i] - 1 le j - p[j] + 1)
    (n) 为读入的串的长度
    枚举一个 (i),动态确定一个决策集合,线段树维护最优解即可
    注意一个细节,线段树维护的时候一个位置可能加入多个值,这些都是可行的,但删除的时候会使所有的值消失,需要特别处理
    (O(n log n))
    但还有扫描线+并查集 (o(n alpha(n))) 的优秀解法(不会)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    
    const int N = 2e5 + 5;
    int p[N << 1], n, len, bz[N << 1];
    char s[N], str[N << 1];
    
    void Manacher()
    {
    	str[0] = '@', str[++n] = '#';
    	scanf("%s", s);
    	len = strlen(s);
    	for(register int i = 0; i < len; i++) str[++n] = s[i], str[++n] = '#';
    	for(register int i = 0; i < len; i++) str[++n] = s[i], str[++n] = '#';
    	str[++n] = '', len = len * 2;
    	int mx = 0, id = 0;
    	for(register int i = 1; i <= n; i++)
    	{
    		p[i] = (i < mx ? min(p[id * 2 - i], mx - i) : 1);
    		while (i - p[i] + len > i + p[i] && str[i + p[i]] == str[i - p[i]]) ++p[i];
    		if (i + p[i] > mx) mx = i + p[i], id = i;
    	}
    }
    
    #define ls (p << 1)
    #define rs (ls | 1)
    int seg[N * 8];
    void update(int p, int l, int r, int x, int v)
    {
    	if (l == r) 
    	{
    		bz[v] = 1, seg[p] = v;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if (x <= mid) update(ls, l, mid, x, v);
    	else update(rs, mid + 1, r, x, v);
    	seg[p] = max(seg[ls], seg[rs]);
    }
    int query(int p, int l, int r, int x, int y)
    {
    	if (x <= l && r <= y) return seg[p];
    	int mid = (l + r) >> 1, res = 0;
    	if (x <= mid) res = query(ls, l, mid, x, y);
    	if (y > mid) res = max(res, query(rs, mid + 1, r, x, y));
    	return res;
    }
    
    int Solve()
    {
    	int ans = 0; len >>= 1;
    	for(register int i = 1; i <= len + 1; i++) update(1, 0, n, i - p[i] + 1, i);
    	for(register int i = 1; i <= n - len; i++)
    	{
    		ans = max(ans, query(1, 0, n, 0, i + p[i] - 1) - i);
    		if (!bz[i]) update(1, 0, n, i - p[i + 1] + 1, 0);
    		update(1, 0, n, i + 1 + len - p[i + 1 + len] + 1, i + 1 + len);
    	}
    	return ans;
    }
    
    int main()
    {
    	Manacher();
    	printf("%d
    ", Solve());
    }
    
  • 相关阅读:
    给vs2012轻松换肤
    几种软件常用授权方式总结
    Discuz X2多人斗地主[消耗论坛积分]小体积版本,仅25MB!
    关于Socket 设置 IPAddress.Any 情况下,出现服务器积极拒绝的问题
    以前看过一个压缩过的.exe,运行会播放长达半小时的动画,却只有60KB,个人认为其中的原理
    VisualSvn Server安装和使用
    socket短时间内重连需注意的问题
    PostgreSQL在何处处理 sql查询之十一
    PostgreSQL在何处处理 sql查询之十三
    PostgreSQL在何处处理 sql查询之十四
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/14999617.html
Copyright © 2020-2023  润新知