zoukankan      html  css  js  c++  java
  • [Codeforces]862F

    题目大意: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
    ",ans);
            }
            else renew(read());
    }
  • 相关阅读:
    USACO 3.3 A Game
    USACO 3.3 Camelot
    USACO 3.3 Shopping Offers
    USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
    USACO 3.3 Riding the Fences
    USACO 3.2 Magic Squares
    USACO 3.2 Stringsobits
    USACO 3.2 Factorials
    USACO 3.2 Contact
    USACO 3.1 Humble Numbers
  • 原文地址:https://www.cnblogs.com/ditoly/p/CF862F.html
Copyright © 2011-2022 走看看