码迷,mamicode.com
首页 > 其他好文 > 详细

[Codeforces]862F - Mahmoud and Ehab and the final stage

时间:2017-09-20 10:15:31      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:复杂度   nod   inline   cin   字符串   线段   pac   tor   位置   

题目大意:n个字符串,支持修改一个位置上的字符串和查询一个区间的子区间中长度乘LCP的最大值,输入字符数和询问数不超过10^5。

做法:求出相邻的LCP长度,区间LCP等于区间最小值,查询分几种情况考虑,一种只有一个串,线段树维护长度最大值即可;若有若干个串,设一个阈值k,若答案的LCP<=k,对于小等k的每一个i,若一个位置的相邻LCP大等i,设为1,否则设为0,即求区间最长连续1,每种i开一棵线段树维护即可;若LCP>k,我们把相邻LCP长度超过k的位置存进set,查询的时候拿出来,直接建笛卡尔树计算答案,由于字符总数有限,这样的位置不会超过L/k个。总时间复杂度为O(nklogn+nL/k),适当调整k,时间复杂度为O(n(nlogn)^0.5)。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<map>
#include<set>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
#define MN 100000
#define N 131072
#define K 50
struct node{int l,r,u,mx;}T[K+5][N*2+5];
node operator+(const node&a,const node&b)
{
    return (node){a.l+a.u*b.l,b.r+b.u*a.r,a.u*b.u,max(max(a.mx,b.mx),a.r+b.l)};
}
string s[MN+5];
int t[N*2+5],v[MN+5],a[MN+5],an,Z[MN+5],zn,L[MN+5],R[MN+5],ans,S[MN+5];
set<int> st;
void change(int k,int x){for(t[k+=N]=x;k>>=1;)t[k]=max(t[k<<1],t[k<<1|1]);}
int query(int l,int r)
{
    int res=0;
    for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1)res=max(res,t[l+1]);
        if( r&1)res=max(res,t[r-1]);
    }
    return res;
}
void change(node*t,int k,node x){for(t[k+=N]=x;k>>=1;)t[k]=t[k<<1]+t[k<<1|1];}
node Query(node*t,int l,int r)
{
    node L,R;int ul=0,ur=0;
    for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1)L=ul?L+t[l+1]:(ul=1,t[l+1]);
        if( r&1)R=ur?t[r-1]+R:(ur=1,t[r-1]);
    }
    return ul?ur?L+R:L:R;
}
void renew(int x)
{
    cin>>s[x];change(x,s[x].size());
    if(v[x]>K)st.erase(x);if(v[x+1]>K)st.erase(x+1);
    for(v[x]=0;v[x]<s[x].size()&&v[x]<s[x-1].size()&&s[x][v[x]]==s[x-1][v[x]];)++v[x];
    for(v[x+1]=0;v[x+1]<s[x].size()&&v[x+1]<s[x+1].size()&&s[x][v[x+1]]==s[x+1][v[x+1]];)++v[x+1];
    if(v[x]>K)st.insert(x);if(v[x+1]>K)st.insert(x+1);
    node a=(node){0,0,0,0},b=(node){1,1,1,1};
    for(int i=1;i<=K;++i)change(T[i],x,v[x]<i?a:b),change(T[i],x+1,v[x+1]<i?a:b);
}
void dfs(int x)
{
    S[x]=1;
    if(L[x])dfs(L[x]),S[x]+=S[L[x]];
    if(R[x])dfs(R[x]),S[x]+=S[R[x]];
    ans=max(ans,v[x]*(S[x]+1));
}
int p(const set<int>::iterator&i){return i!=st.end()?*i:MN+1;}
int main()
{
    int n,m,i,l,r,z;
    n=read();m=read();
    for(i=1;i<=n;++i)renew(i);
    while(m--)
        if(read()==1)
        {
            l=read();r=read();
            ans=query(l,r);
            if(l<r)for(i=1;i<=K;++i)z=Query(T[i],l+1,r).mx,ans=max(ans,i*(z?z+1:0));
            set<int>::iterator it=st.upper_bound(l);
            for(z=p(it);z<=r;)
            {
                for(a[an=1]=z;(z=p(++it))<=r&&z==a[an]+1;)a[++an]=z;
                for(i=1,zn=0;i<=an;++i)
                {
                    L[a[i]]=R[a[i]]=0;
                    while(zn&&v[a[i]]<v[a[Z[zn]]])L[a[i]]=a[Z[zn--]];
                    R[a[Z[zn]]]=a[i];Z[++zn]=i;
                }
                dfs(a[Z[1]]);
            }
            printf("%d\n",ans);
        }
        else renew(read());
}

 

[Codeforces]862F - Mahmoud and Ehab and the final stage

标签:复杂度   nod   inline   cin   字符串   线段   pac   tor   位置   

原文地址:http://www.cnblogs.com/ditoly/p/CF862F.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!