BZOJ2120:数颜色(分块版)

浅谈分块:https://www.cnblogs.com/AKMer/p/10369816.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2120

树套树做法:https://www.cnblogs.com/AKMer/p/10189008.html

对于每个块维护块内\(pre\)上升的数组即可,每次查找直接\(lower\) \(bound\)一下,其它的跟树套树版的没什么区别。

时间复杂度:\(O(nlog\sqrt{n}+m\sqrt{n}log\sqrt{n})\)

空间复杂度:\(O(n)\)

代码如下:

#include <set>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=1e4+5,maxv=1e6+5;;

char s[5];
int n,m,block;
set<int>pos[maxv];
set<int>::iterator it;
int L[105],R[105],f[105][105];
int col[maxn],bel[maxn],pre[maxv],now[maxv];

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

void build(int id) {
    for(int i=L[id];i<=R[id];i++)
        f[id][i-L[id]+1]=pre[i];
    sort(f[id]+1,f[id]+R[id]-L[id]+2);
}

int main() {
    n=read(),m=read(),block=sqrt(n);
    for(int i=1;i<=n;i++) {
        col[i]=read(),bel[i]=(i-1)/block+1;
        if(pos[col[i]].empty())
            pos[col[i]].insert(0),pos[col[i]].insert(n+1);
        if(bel[i]!=bel[i-1])R[bel[i-1]]=i-1,L[bel[i]]=i;
        pre[i]=now[col[i]],now[col[i]]=i,pos[col[i]].insert(i);
    }R[bel[n]]=n;
    for(int i=1;i<=bel[n];i++)build(i);
    while(m--) {
        scanf("%s",s+1);
        if(s[1]=='Q') {
            int ans=0,l=read(),r=read();
            if(bel[l]==bel[r]) {
                for(int i=l;i<=r;i++)if(pre[i]<l)ans++;
            }
            else {
                for(int i=l;i<=R[bel[l]];i++)if(pre[i]<l)ans++;
                for(int i=L[bel[r]];i<=r;i++)if(pre[i]<l)ans++;
                for(int i=bel[l]+1;i<bel[r];i++)
                    ans+=lower_bound(f[i]+1,f[i]+R[i]-L[i]+2,l)-f[i]-1;
            }
            printf("%d\n",ans);
        }
        else {
            int p=read(),c=read(),tmp=col[p],l,r;
            if(pos[c].empty())pos[c].insert(0),pos[c].insert(n+1);
            pos[tmp].erase(pos[tmp].find(p));
            it=pos[tmp].lower_bound(p);
            if(it!=pos[tmp].end()&&it!=pos[tmp].begin())
                r=*it,it--,l=*it,pre[r]=l,build(bel[r]);
            it=pos[c].lower_bound(p);
            if(it!=pos[c].end())pre[*it]=p,build(bel[*it]);
            if(it!=pos[c].begin())it--,pre[p]=*it,build(bel[p]);
            pos[c].insert(p);
            col[p]=c;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKMer/p/10373457.html