萌新求助分块TAT
查看原帖
萌新求助分块TAT
311306
dk_qwq楼主2023/8/28 14:47
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
namespace INPUT{
    char buf[1<<20],*p1,*p2;
    #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
}
using namespace INPUT;
template<typename T>
inline T read(){
    T x=0,p=1;
    char ch=gc();
    for(;ch<'0'||ch>'9';ch=gc())
        if(ch=='-') p=-1;
    for(;ch>='0'&&ch<='9';ch=gc())
        x=(x<<3)+(x<<1)+(ch^48);
    return x*p;
}
#include<assert.h>
#pragma GCC optimize(2)

const int N=100005,M=350;
#define B 310
int pos[N],DL[M],DR[M];
int fa[M][N],siz[M][N];
int find(int p,int x) {
    assert(x>0&&x<N);
    return fa[p][x]==x?x:fa[p][x]=find(p,fa[p][x]);
}
void Union(int p,int u,int v){
    u=find(p,u),v=find(p,v);
    fa[p][v]=u,siz[p][u]+=siz[p][v];
}
int n,m,a[N];
int LazyTag[M];
int Mx[M];
void build(int p,int l=1,int r=n,int x=0){

    //可能存在经过change改变postion导致为清空的行为
    for(int i=DL[p];i<=DR[p];i++) a[i]=find(p,a[i]);
    for(int i=DL[p];i<=DR[p];i++) fa[p][a[i]]=a[i],siz[p][a[i]]=0;
    // for(int i=1;i<=1e5;i++) fa[p][i]=i,siz[p][i]=0;
    Mx[p]=0;
    for(int i=DL[p];i<=DR[p];i++){
        a[i]+=LazyTag[p];
        if(l<=i&&i<=r&&a[i]>x) a[i]-=x;
        assert(a[i]>0&&a[i]<N);
        Mx[p]=max(Mx[p],a[i]);
        siz[p][a[i]]++;
    }
    LazyTag[p]=0;
}
void Change(int p,int x){
    if(Mx[p]<=x) return ;
    if(2*x>=Mx[p]){
        for(int i=x+1-LazyTag[p];i<=Mx[p];i++){
            assert(i>0&&i<N);
            if(!siz[p][i]) continue;
            assert(i-x>0&&i-x<N);
            Union(p,fa[p][i-x],fa[p][i]);
        }
    }
    else {
        for(int i=1-LazyTag[p];i<=min(Mx[p],x-LazyTag[p]);i++){
            assert(i>0&&i<N);
            if(!siz[p][i]) continue;
            if(Mx[p]<i+LazyTag[p]+x) Mx[p]=i+LazyTag[p]+x;
            assert(1<=i+x&&i+x<N);
            Union(p,fa[p][i+x],fa[p][i]);
        }
        LazyTag[p]-=x;
    }
}
void Change(int l,int r,int x){
    int L=pos[l],R=pos[r];
    if(L+1<=R){
        build(L,l,DR[L],x),build(R,DL[R],r,x);
        for(int i=L+1;i<=R-1;i++) Change(i,x);
    }
    else build(L,l,r,x);
}
int Query(int p,int l,int r,int x){
    int ans=0;
    for(int i=l;i<=r;i++)
        if(find(p,a[i])+LazyTag[p]==x) ans++;
    return ans;
}
int Query(int l,int r,int x){
    int L=pos[l],R=pos[r];
    int ans=0;
    if(L+1<=R){
        ans+=Query(L,l,DR[L],x),ans+=Query(R,DL[R],r,x);
        for(int i=L+1;i<=R-1;i++) {
            assert(1<=x-LazyTag[i]&&x-LazyTag[i]<N);
            ans+=siz[i][find(i,x-LazyTag[i])];
        }
    }
    else ans+=Query(L,l,r,x);
    return ans;
}
int main(){
    // freopen("CF896E.in","r",stdin);
    // freopen("CF896E.out","w",stdout);
    n=read<int>(),m=read<int>();
    for(int i=1;i<=n;i++) pos[i]=(i-1)/B+1;
    int sz=(n-1)/B+1;
    for(int i=1;i<=sz;i++)
        DL[i]=(i-1)*B+1,DR[i]=min(i*B,n);
    for(int i=1;i<=n;i++) a[i]=read<int>();
    for(int i=1;i<=sz;i++)
        for(int v=1;v<=1e5;v++) fa[i][v]=v;
    for(int i=1;i<=sz;i++) build(i);


    int op,l,r,x;
    for(int i=1;i<=m;i++){
        op=read<int>();
        l=read<int>(),r=read<int>(),x=read<int>();

        if(op==1) Change(l,r,x);
        if(op==2) printf("%d\n",Query(l,r,x));
    }
}
2023/8/28 14:47
加载中...