Dynamic len

topic

There are n numbers numbered from 0→n-1, two operations:
QLR: Ask how many different numbers are there in the number numbered L→R-1 MXY: There are m operations
to change the number numbered X to Y

analyze

Since it is a single-point modification and query, let's consider partitioning.

First, define \(next_{i}\) to represent the position of the first number after \ (i\) that is the same as the number numbered \(i\) .
Next, we connect \(i\) to \(next_{i}\) with an edge.
Then you will find that when the edge is processed, the query operation is easily solved;

query operation

Suppose now you want to query \([x, y]\) ,
write picture description here
where next, and their connected edges are:
write picture description here
find, the number of numbers \(a\) and the number of numbers \(next_a\) and The number numbered \(b\) and the number numbered \(next_b\) are repeated.
Then the repeated ones must be subtracted,
and the number numbered \(next_c\) is not in \([x, y]\) , so there is no need to subtract.
We come to a conclusion: \(\color{red}{When next_i<=y, the number numbered i must be repeated, so we only record the last one, that is, the one with next_i>y}\)
Then How to deal with it?
For parts that are not a whole block, brute force. Time complexity \(O(2\sqrt{n})\) .
For the part of the whole block, sort the whole block according to \(next_{i}\) , and find the answer in two parts.

Modify operation

We redefine \(last_{i}\) to represent the position of the first number that is the same as the number numbered \(i\) before \(i\) .
Then connect \(i\) to \(last_{i}\) with an edge;
suppose we modify the position x,
write picture description here
then, because x is modified to another value, so \(next[last[x]]\) will Just fix it to \(next[x]\) , and \(last[next[x]]\) will be changed to \(last[x]\)
Then, I found that \(next[last[x]]\) ) changed, so reorder the block where \(last[x]\) is located.

Then, the new \(last and next\) at position x is processed .
Suppose the start and end of the block where x is located is s and t.
write picture description here
Handling \(last\) :
We first violently check whether y has appeared in the position of x-1~s, and if so, modify \(last[x]\) and \(next[last[x]]\) .
Otherwise, look at the previous block,
and then define \(sum[i][j]\) to indicate how many times the number j appears in the i-th block.
If you find it, you can modify it.
Handling \(next\) is similar.
Remember, if the \(next\) of a certain position is modified, the block where this position is located will be sorted.

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=50005;
using namespace std;
int a[N*2],n,m,ans,next[N*2],last[N*2],part[N][2],size,as[N*2],pos[N*2],stead[1000005],sum[250][N*2],tot,color[N*2],num;
bool cmp(int x,int y)
{
    return next[x]<next[y];
}
int preblock()
{
    size=sqrt(n);
    for(int i=1;i<=n;i+=size)
    {
        part[++tot][0]=i;
        if(i+size-1>n)
            part[tot][1]=n;
                else
                    part[tot][1]=i+size-1;
    }
    for(int i=1;i<=tot;i++)
        for(int j=part[i][0];j<=part[i][1];j++)
        {
            sum[i][stead[a[j]]]++;
            pos[j]=i;
        }
}
int prenexus()
{
    memset(color,0,sizeof(color));
    for(int i=0;i<=n;i++)
    {
        last[i]=color[stead[a[i]]];
        color[stead[a[i]]]=i;
    }
    memset(color,0,sizeof(color));
    for(int i=n;i>=0;i--)
    {
        next[i]=color[stead[a[i]]];
        if(!next[i])
            next[i]=maxlongint;
        color[stead[a[i]]]=i;
    }
}
int so(int x)
{
    sort(as+part[x][0],as+part[x][1]+1,cmp);
}
int fs(int x,int y,int y1)
{
    for(int i=x;i<=y;i++)
        if(next[i]>y1)
            ans++;
}
int zt(int x,int y,int y1)
{
    int ll=x-1,rr=y;
    while(ll<rr-1)
    {
        int mid=(ll+rr)/2;
        if(next[as[mid]]<=y1) ll=mid;
            else rr=mid; 
    }
    int q=0;
    if(next[as[rr]]<=y1) q=rr;
        else q=ll;
    ans+=y-x+1-(q-x+1);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(!stead[a[i]])
        {
            stead[a[i]]=++num;
        }
    }
    preblock();
    prenexus();
    for(int i=1;i<=n;i++) as[i]=i;
    for(int i=1;i<=tot;i++) so(i);
    for(int k=1;k<=m;k++)
    {
        char c=getchar();
        while(c!='Q' && c!='M') c=getchar();
        int x,y;
        scanf(" %d %d",&x,&y);
        x+=1;
        if(c=='Q')
        {
            ans=0;
            int l=pos[x],r=pos[y];
            if(l==r)
            {
                for(int i=x;i<=y;i++)
                    if(next[i]>y) ans++;
                    printf("%d\n",ans);
                continue;
            }
            if(x>part[l][0])
            {
                for(int i=x;i<=part[l][1];i++)
                    if(next[i]>y) ans++;
                l++;
            }
            if(y<part[r][1])
            {
                for(int i=part[r][0];i<=y;i++)
                    if(next[i]>y) ans++;
                r--;
            }
            for(int i=l;i<=r;i++)
                zt(part[i][0],part[i][1],y);
            printf("%d\n",ans);
        }
        else
        {
            bool q=true;
            if(!stead[y])
            {
                stead[y]=++num;
                q=false;
            }
            next[last[x]]=next[x];
            if(next[x]!=maxlongint)
                last[next[x]]=last[x];
            sum[pos[x]][stead[a[x]]]--;
            sum[pos[x]][stead[y]]++;
            so(pos[last[x]]);
            a[x]=y;
            if(!q)
            {
                last[x]=0;
                next[x]=maxlongint;
            }
            else
            {
                int p=0,p1=0;
                for(int i=x-1;i>=part[pos[x]][0];i--)
                    if(a[i]==y)
                    {
                        p=i;
                        break;
                    }
                if(!p)
                {
                    for(int i=pos[x]-1;i>=1;i--)
                    {
                        if(sum[i][stead[y]])
                        {
                            for(int j=part[i][1];j>=part[i][0];j--)
                                if(a[j]==y)
                                {
                                    p=j;
                                    break;
                                }
                            break;
                        }
                    }
                }
                if(p)
                {
                    last[x]=p;
                    next[p]=x;
                    so(pos[p]);
                }
                else
                    last[x]=0;
                for(int i=x+1;i<=part[pos[x]][1];i++)
                    if(a[i]==y)
                    {
                        p1=i;
                        break;
                    }
                if(!p1)
                {
                    for(int i=pos[x]+1;i<=tot;i++)
                    {
                        if(sum[i][stead[y]])
                        {
                            for(int j=part[i][0];j<=part[i][1];j++)
                                if(a[j]==y)
                                {
                                    p1=j;
                                    break;
                                }
                            break;
                        }
                    }
                }
                if(p1)
                {
                    next[x]=p1;
                    last[p1]=x;
                    so(pos[x]);
                }
                else
                    next[x]=maxlongint;
            }
            so(pos[x]);
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326032370&siteId=291194637