[ZOJ4089]Little Sub and Isomorphism Sequences

版权声明:辛辛苦苦码字,你们转载的时候记得告诉我 https://blog.csdn.net/dxyinme/article/details/86559788

Time Limit: 3 Seconds
Memory Limit: 65536 KB

Little Sub has a sequence A 1 , A 2 , A 3 , . . . , A N A_1,A_2,A_3,...,A_N . Now he has a problem for you.
Two sequences X 1 , X 2 , X 3 , . . . , X u X_1,X_2,X_3,...,X_u of length u u and of X 1 , X 2 , X 3 , . . . , X v X_1,X_2,X_3,...,X_v length v v are considered isomorphic when they meet all the following two conditions:
1. u = v 1. u = v ;
2. 2. Define o c c ( S , k ) occ(S,k) as the number of times integer k k occur in sequence S S . For each integer k k in [ 1 , 1 0 9 ] [1,10^9] , o c c ( X , k ) = o c c ( Y , k ) occ(X,k)=occ(Y,k) always holds.

Now we have M M operations for A A . and there are two kinds of operations:
1 1 x x y y : Change A x A_x to y y ( 1 < = x < = N , 1 < = y < = 1 0 9 ) (1<=x<=N , 1<=y<=10^9) ;
2 2 : Query for the greatest k ( 1 < = k < N ) k(1<=k<N) that there exist two integers i i and j j ( 1 < = i < j < N k + 1 ) (1<=i<j<N-k+1) and A i , A i + 1 , A i + 2 , . . . , A i + k 1 A_i,A_{i+1},A_{i+2},...,A_{i+k-1} is isomorphic with A j , A j + 1 , A j + 2 , . . . , A j + k 1 A_j,A_{j+1},A_{j+2},...,A_{j+k-1} . Specially, if there is no such k k , please output “ 1 -1 ” (without quotes) instead.

Input

There are multiple test cases. The first line of the input contains an integer T ( 1 < = T < = 5 ) T(1<=T<=5) , indicating the number of test cases. For each test case:
The first line ontains two integers N , M ( 1 < = N , M < = 1 0 5 ) N,M(1<=N,M<=10^5) .
The second line contains N N integers A 1 , A 2 , A 3 , . . . , A N ( 1 < = A i < = 1 0 9 ) A_1,A_2,A_3,...,A_N(1<=A_i<=10^9) .
In the following M M lines, each line contains one operation. The format is described above.

Output

For each operation 2, output one line containing the answer.

Sample Input

1
3 5
1 2 3
2
1 3 2
2
1 1 2
2

Sample Output

-1
1
2

题意:
给一个序列,有两个操作,第一个操作是单点修改,第二个操作是询问整个序列中最长的两个不重合同构子串的长度。(同构的定义是字串中所有出现的数字,在两个子串中的出现次数都相同)
题解:
我们可以发现,最长不重合同构子串肯定是相互重合的,只有两端是不重合的,那么我们只需要维护 A [ i ] A[i] 中相同数字的最大距离 w w 就可以了,答案就是 w + 1 w+1
离散化,开20万个set,存数字 x x 的位置信息,然后用线段树维护 w + 1 w+1 ,就可以了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#define LiangJiaJun main
using namespace std;
set<int>pos[200004];
map<int,int>mert;
int up;
int tr[800004],n,m;
struct als{
    int x,lp;
}a[200004],A[100004];
struct mot{
    int type,x,g,lp;
}work[100004];
inline bool dex(als X,als Y){
    return X.x<Y.x;
}

void update(int x){
     if(pos[x].size()<=1)tr[x+up]=-1;
     else{
        tr[x+up]=(*--pos[x].end())-(*pos[x].begin());
     }
     int now=x+up;now>>=1;
     while(now>=1){
        tr[now]=max(tr[now<<1],tr[now<<1|1]);
        now>>=1;
     }
}
int w33ha(){
    mert.clear();
    scanf("%d%d",&n,&m);
    int cnt=n;
    for(int i=1;i<=n;i++){
        scanf("%d",&A[i].x);
        a[i]=A[i];
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&work[i].type);
        if(work[i].type==1){
            scanf("%d%d",&work[i].g,&work[i].x);
            a[++cnt].x=work[i].x;
        }
    }
    sort(a+1,a+cnt+1,dex);
    a[0].x=0;
    int om=0;
    for(int i=1;i<=cnt;i++){
        if(a[i].x!=a[i-1].x){
            mert[a[i].x]=++om;
            a[i].lp=om;
            pos[om].clear();
        }
    }
    for(int i=1;i<=n;i++)A[i].lp=mert[A[i].x];
    for(int i=1;i<=m;i++){
        if(work[i].type==1)work[i].lp=mert[work[i].x];
    }
    for(int i=1;i<=n;i++){
        pos[A[i].lp].insert(i);
    }
    up=1;
    while(up<cnt+2)up<<=1;
    for(int i=up;i>=1;i--){
        tr[i<<1]=-1;
        tr[i<<1|1]=-1;
    }
    for(int i=1;i<=cnt;i++){
        if(pos[a[i].lp].size()<=1)tr[a[i].lp+up]=-1;
        else{
            tr[a[i].lp+up]=(*--pos[a[i].lp].end())-(*pos[a[i].lp].begin());
        }
    }
    for(int i=up;i>=1;i--)tr[i]=max(tr[i<<1],tr[i<<1|1]);
    for(int i=1;i<=m;i++){
        if(work[i].type==1){
            int g=work[i].g;
            pos[A[g].lp].erase(g);
            pos[work[i].lp].insert(g);
            update(A[g].lp);
            update(work[i].lp);
            A[g].lp=work[i].lp;
            A[g].x=work[i].x;
        }
        else{
            printf("%d\n",tr[1]);
        }
    }
    return 0;
}
int LiangJiaJun(){
    int T;scanf("%d",&T);
    while(T--)w33ha();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dxyinme/article/details/86559788
今日推荐