拍了十几万组小数据,没出问题,但是大数据一拍就挂,但是大数据又不能查错,因为大佬们有好的数据生成器,所以求一组hack掉我的小数据。
又或者是我哪里写挂了,所以跑不了大数据呢?
#include<bits/stdc++.h>
#define ll long long
#define inf 2147483647
using namespace std;
int n1,m,t1,t2,L1[650],R1[650],L2[650],R2[650],pos1[2000010],pos2[2000010],a[200010],n2,b[200010],ql1,ql2,rt[650][200010],f[200010];
int cnt1[650][650],cnt2[650][200010],ton1[200100],ton2[200100];
inline int read()
{
int k=0,f=0;char c=getchar();
for(;!isdigit(c);c=getchar()) f|=c=='-';
for(;isdigit(c);c=getchar()) k=(k<<1)+(k<<3)+(c^48);
return f?-k:k;
}
inline int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
inline void bing(int x,int y)
{
x=find(x),y=find(y);
if(x!=y) f[x]=y;
}
inline void renew(int x)
{
for(int i=L1[x];i<=R1[x];i++)
{
rt[x][a[i]]=0;
f[i]=i;
}
for(int i=L1[x];i<=R1[x];i++)
{
if(!rt[x][a[i]]) rt[x][a[i]]=i;
else bing(i,rt[x][a[i]]);
}
}
inline void build1()
{
ql1=sqrt(n1);
t1=n1/ql1;
for(int i=1;i<=t1;i++)
{
L1[i]=R1[i-1]+1;
R1[i]=i*ql1;
}
if(R1[t1]!=n1)
{
t1++;
L1[t1]=R1[t1-1]+1;
R1[t1]=n1;
}
for(int i=1;i<=t1;i++)
{
for(int j=L1[i];j<=R1[i];j++)
{
pos1[j]=i;
}
renew(i);
for(int j=1;j<=R1[i];j++) cnt2[i][a[j]]++;
}
}
inline void build2()
{
n2=100000;
ql2=sqrt(n2);
t2=n2/ql2;
for(int i=1;i<=t2;i++)
{
L2[i]=R2[i-1]+1;
R2[i]=i*ql2;
}
if(R2[t2]!=n2)
{
t2++;
L2[t2]=R2[t2-1]+1;
R2[t2]=n2;
}
for(int i=1;i<=t2;i++)
{
for(int j=L2[i];j<=R2[i];j++)
{
pos2[j]=i;
}
}
for(int i=1;i<=t1;i++)
{
for(int j=1;j<=R1[i];j++)
{
cnt1[i][pos2[a[j]]]++;
}
}
}
inline void update(int l,int r,int x,int y)
{
if(x==y) return;
int q1=pos1[l],p1=pos1[r],s=0,ss=0;
if(q1==p1)
{
for(int i=L1[q1];i<=R1[q1];i++) a[i]=a[find(i)];
for(int i=l;i<=r;i++)
{
if(a[i]==x)
{
a[i]=y;
s++;
}
}
renew(q1);
for(int i=q1;i<=t1;i++)
{
cnt1[i][pos2[x]]-=s;
cnt2[i][x]-=s;
cnt1[i][pos2[y]]+=s;
cnt2[i][y]+=s;
}
return;
}
//先处理每个整块
for(int i=q1+1;i<p1;i++)
{
ton1[i]=cnt2[i][x]-cnt2[i-1][x];
ton2[i]=cnt2[i][x]-cnt2[i-1][x];
}
//散块对后面的贡献
//更新为实际值
for(int i=L1[q1];i<=R1[q1];i++) a[i]=a[find(i)];
for(int i=L1[p1];i<=R1[p1];i++) a[i]=a[find(i)];
for(int i=l;i<=R1[q1];i++)
{
if(a[i]==x)
{
s++;
a[i]=y;
}
}
for(int i=q1;i<=t1;i++)
{
cnt1[i][pos2[x]]-=s;
cnt2[i][x]-=s;
cnt1[i][pos2[y]]+=s;
cnt2[i][y]+=s;
}
s=0;
for(int i=L1[p1];i<=r;i++)
{
if(a[i]==x)
{
s++;
a[i]=y;
}
}
for(int i=p1;i<=t1;i++)
{
cnt1[i][pos2[x]]-=s;
cnt2[i][x]-=s;
cnt1[i][pos2[y]]+=s;
cnt2[i][y]+=s;
}
renew(q1);
renew(p1);
//整块对后面的贡献
for(int i=p1;i<=t1;i++)
{
cnt1[i][pos2[x]]-=cnt2[p1-1][x]-cnt2[q1][x];
cnt2[i][x]-=cnt2[p1-1][x]-cnt2[q1][x];
cnt1[i][pos2[y]]+=cnt2[p1-1][x]-cnt2[q1][x];
cnt2[i][y]+=cnt2[p1-1][x]-cnt2[q1][x];
}
//修改整块对自己的贡献
s=0;
for(int i=q1+1;i<p1;i++)
{
if(rt[i][x])
{
if(!rt[i][y]) rt[i][y]=rt[i][x];
else bing(rt[i][x],rt[i][y]);
a[rt[i][y]]=y;
rt[i][x]=0;
}
s+=ton1[i];
ss+=ton2[i];
cnt1[i][pos2[y]]+=s;
cnt2[i][y]+=ss;
cnt1[i][pos2[x]]-=s;
cnt2[i][x]-=ss;
}
for(int i=q1+1;i<p1;i++) ton1[i]=ton2[i]=0;
}
inline int get_kth(int l,int r,int k)
{
int q1=pos1[l],p1=pos1[r];
if(q1==p1)
{
for(int i=l;i<=r;i++) a[i]=a[find(i)];
for(int i=l;i<=r;i++)
{
ton1[pos2[a[i]]]++;
ton2[a[i]]++;
}
for(int i=1;i<=t2;i++)
{
if(k-ton1[i]<=0)
{
for(int j=L2[i];j<=R2[i];j++)
{
k-=ton2[j];
if(k<=0)
{
for(int w=l;w<=r;w++)
{
ton1[pos2[a[w]]]--;
ton2[a[w]]--;
}
return j;
}
}
}
k-=ton1[i];
}
}
for(int i=l;i<=R1[q1];i++) a[i]=a[find(i)];
for(int i=L1[p1];i<=r;i++) a[i]=a[find(i)];
for(int i=l;i<=R1[q1];i++)
{
ton1[pos2[a[i]]]++;
ton2[a[i]]++;
}
for(int i=L1[p1];i<=r;i++)
{
ton1[pos2[a[i]]]++;
ton2[a[i]]++;
}
for(int i=1;i<=t2;i++)
{
if(k-cnt1[p1-1][i]+cnt1[q1][i]-ton1[i]<=0)
{
for(int j=L2[i];i<=R2[i];j++)
{
k-=cnt2[p1-1][j]-cnt2[q1][j]+ton2[j];
if(k<=0)
{
for(int w=l;w<=R1[q1];w++)
{
ton1[pos2[a[w]]]--;
ton2[a[w]]--;
}
for(int w=L1[p1];w<=r;w++)
{
ton1[pos2[a[w]]]--;
ton2[a[w]]--;
}
return j;
}
}
}
k-=cnt1[p1-1][i]-cnt1[q1][i]+ton1[i];
}
return 114514;
}
signed main()
{
n1=read(),m=read();
for(int i=1;i<=n1;i++) a[i]=read();
build1();
build2();
while(m--)
{
int op=read(),l=read(),r=read(),x=read();
if(op==1) update(l,r,x,read());
else printf("%d\n",get_kth(l,r,x));
}
return 0;
}