萌新求助第二分块
  • 板块学术版
  • 楼主FWRP
  • 当前回复4
  • 已保存回复4
  • 发布时间2022/5/28 16:50
  • 上次更新2023/10/28 00:27:11
查看原帖
萌新求助第二分块
669363
FWRP楼主2022/5/28 16:50

rt

题面

#include<bits/stdc++.h>
#define fep(i,l,r) for(int i=l;i<=r;i++)
#define defep(i,r,l) for(int i=r;i>=l;i--)
#define fst first
#define scd second
#define lowbit(x) ((x)&(-x))
#define pb(a) push_back(a)
#define sqt(x) (int)(floor(sqrt((long double) x + 1e-16)) )
#define sqr(x) ((x)*(x))
#define Chtholly(x) ios::sync_with_stdio(x)

using namespace std;
const int M=400;
const int N=1e5+123+M;

int blk;

#define Getl(x) ((x-1)*blk+1)
#define Getr(x) (x*blk)

int rt[M][N],cnt[M][N],mx[M],del[M],a[N],bel[N];
int n,m;
int fa[N];

int Findfa(int x){
    if(x==fa[x])return x;
    return fa[x]=Findfa(fa[x]);
}
void Merge(int x,int y,int b){
    //把x合并到y
    //此时x,y是值
    if(rt[b][y]==0){
        rt[b][y]=rt[b][x];rt[b][x]=0;
        cnt[b][y]=cnt[b][x];cnt[b][x]=0;
        a[rt[b][y]]=y;
        return ;
    }
    cnt[b][y]+=cnt[b][x],cnt[b][x]=0;
    x=rt[b][x],y=rt[b][y];
    //合并b块中的x,y的值
    //此时x,y是下标
    if(x==0)return ;
    x=Findfa(x),y=Findfa(y);
    fa[x]=y;//把x集合指向y
}

int b[N];

void Reset(int x){
    for(int i=Getl(x);i<=Getr(x);i++){
        rt[x][a[i]]=cnt[x][a[i]]=0,b[i]=a[Findfa(i)]-del[x];
    }
    for(int i=Getl(x);i<=Getr(x);i++){
        a[i]=b[i];
    }
    del[x]=0;
}

void Update(int x){
    mx[x]=0;
    for(int i=Getl(x);i<=Getr(x);i++)
        if(!rt[x][a[i]])rt[x][a[i]]=i;
    for(int i=Getl(x);i<=Getr(x);i++){
        cnt[x][a[i]]++;
    }
    for(int i=Getl(x);i<=Getr(x);i++)mx[x]=max(mx[x],a[i]);
    for(int i=Getl(x);i<=Getr(x);i++)
        fa[i]=rt[x][a[i]];
}

void Modify(int l,int r,int x){
    int L=bel[l],R=bel[r];
    if(L==R){
        Reset(L);
        for(int i=l;i<=r;i++)
            if(a[i]>x)a[i]-=x;
        Update(L);
    }
    else {
        Reset(L),Reset(R);
        for(int i=l;i<=Getr(L);i++)
            if(a[i]>x)a[i]-=x;
        for(int i=Getl(R);i<=r;i++)
            if(a[i]>x)a[i]-=x;
        Update(L),Update(R);
        for(int i=L+1;i<=R-1;i++){
            if(mx[i]<=x)continue;
            if(mx[i]-del[i]<=x*2){
                for(int j=x+del[i]+1;j<=mx[i];j++)
                    {Merge(j,j-x,i);}
                for(int j=x+del[i];j>=1;j--)
                    if(cnt[i][j]){mx[i]=j;break;}
            }
            if(mx[i]-del[i]>x*2){
                for(int j=del[i]+1;j<=x+del[i];j++)
                    Merge(j,j+x,i);
                del[i]+=x;
            }
        }
    }
}

int Getans(int l,int r,int x){
    int L=bel[l],R=bel[r],ans=0;
    if(L==R){
        Reset(L);
        for(int i=l;i<=r;i++)
            if(a[i]==x)ans++;
        Update(L);
    }
    else{
        Reset(L),Reset(R);
        for(int i=l;i<=Getr(L);i++)
            if(a[i]==x)ans++;
        for(int i=Getl(R);i<=r;i++)
            if(a[i]==x)ans++;
        for(int i=L+1;i<=R-1;i++){
            if(x+del[i]<=1e5)ans+=cnt[i][x+del[i]];
        }
        Update(L);Update(R);
    }
    return ans;
}

signed main(){
    Chtholly(0);
    cin>>n>>m;blk=sqrt(n);
    for(int i=1;i<=n;i++)
        cin>>a[i],bel[i]=(i-1)/blk+1,cnt[bel[i]][a[i]]++;
    for(int i=1;i<=n;i++)mx[bel[i]]=max(mx[bel[i]],a[i]);
    for(int i=1;i<=n;i++)
        if(!rt[bel[i]][a[i]])rt[bel[i]][a[i]]=i;
    for(int i=1;i<=n;i++)fa[i]=rt[bel[i]][a[i]];
    while(m--){
        int kd,l,r,x;
        cin>>kd>>l>>r>>x;
        if(kd==1)
            Modify(l,r,x);
        if(kd==2)
            cout<<Getans(l,r,x)<<endl;
    }
    return 0;
}
2022/5/28 16:50
加载中...