BZOJ 2120/BZOJ 2453

Posted on 2016-07-18 20:45  ziliuziliu  阅读(154)  评论(0编辑  收藏  举报

分块傻逼题。

memset很慢的。。。而且其实也没有用。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 10050
#define maxm 1000500
using namespace std;
int n,m,col[maxn],pre[maxn],last[maxm],b[maxm],pos[maxn],len,num;
int x,y;
char s[5];
void reset(int x)
{
    int l=(x-1)*len+1,r=min(x*len,n);
    for (int i=l;i<=r;i++)
        b[i]=pre[i];
    sort(b+l,b+r+1);
}
void build()
{
    if (n%len==0) num=n/len;
    else num=n/len+1;
    for (int i=1;i<=num;i++)
        reset(i);
}
void change()
{
    scanf("%d%d",&x,&y);
    for(int i=1;i<=n;i++) last[col[i]]=0;
    col[x]=y;
    for (int i=1;i<=n;i++)
    {
        int regis=pre[i];
        pre[i]=last[col[i]];last[col[i]]=i;
        if (regis!=pre[i]) reset(pos[i]);
    }
}
int find(int pos,int x)
{
    int l=(pos-1)*len+1,r=min(pos*len,n);
    int re=l;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        if (b[mid]<x) l=mid+1;
        else r=mid-1;
    }
    return l-re;
}
void ask()
{
    scanf("%d%d",&x,&y);
    int ans=0;
    if (pos[x]==pos[y])
    {
        for (int i=x;i<=y;i++)
            if (pre[i]<x) ans++;
    }
    else
    {
        for (int i=x;i<=pos[x]*len;i++)
            if (pre[i]<x) ans++;
        for (int i=(pos[y]-1)*len+1;i<=y;i++)
            if (pre[i]<x) ans++;
        for (int i=pos[x]+1;i<=pos[y]-1;i++)
            ans+=find(i,x);
    }
    printf("%d\n",ans);
}
int main()
{
    scanf("%d%d",&n,&m);
    len=int(sqrt(n)+log(2*n)/log(2));
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&col[i]);
        pre[i]=last[col[i]];
        last[col[i]]=i;
        pos[i]=(i-1)/len+1;
    }
    build();
    for (int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (s[0]=='Q') ask();
        else change();
    }
    return 0;
}