将所有权值离散化,建立权值线段树,维护区间内数字个数以及对数的和,用于比较乘积大小。
对于每个连通块维护一棵权值线段树,合并时用线段树合并。
对于操作3和4,暴力删除所有不合法节点,然后一并修改后插入线段树即可。
时间复杂度$O(m\log m)$。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=400010,M=7000000;
int n,m,i,x,y,op[N][3],b[N],U,f[N],T[N],cnt;
int tot,l[M],r[M],v[M];double s[M],L[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline int lower(int x){int l=1,r=U,mid,t;while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;return t;
}
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
void ins(int&x,int a,int b,int c,int d,double e){if(!x)x=++tot;v[x]+=d,s[x]+=e;if(a==b)return;int mid=(a+b)>>1;if(c<=mid)ins(l[x],a,mid,c,d,e);else ins(r[x],mid+1,b,c,d,e);
}
inline void up(int x){v[x]=v[l[x]]+v[r[x]];s[x]=s[l[x]]+s[r[x]];
}
void del(int x,int a,int b,int c,int d){if(!v[x])return;if(a==b){cnt+=v[x],v[x]=0,s[x]=0;return;}int mid=(a+b)>>1;if(c<=mid)del(l[x],a,mid,c,d);if(d>mid)del(r[x],mid+1,b,c,d);up(x);
}
int merge(int x,int y,int a,int b){if(!x)return y;if(!y)return x;if(a==b){v[x]+=v[y];s[x]+=s[y];return x;}int mid=(a+b)>>1;l[x]=merge(l[x],l[y],a,mid);r[x]=merge(r[x],r[y],mid+1,b);return up(x),x;
}
inline int kth(int x,int k){int a=1,b=U,mid;while(a<b){mid=(a+b)>>1;if(v[l[x]]>=k)b=mid,x=l[x];else k-=v[l[x]],a=mid+1,x=r[x];}return a;
}
int main(){read(m);for(i=1;i<=m;i++){read(op[i][0]),read(op[i][1]);if(op[i][0]>1&&op[i][0]<7)read(op[i][2]);if(op[i][0]==1)b[++U]=op[i][1];if(op[i][0]==3||op[i][0]==4)b[++U]=op[i][2];}sort(b+1,b+U+1);for(i=1;i<=U;i++)L[i]=log(b[i]);for(i=1;i<=m;i++){x=op[i][1],y=op[i][2];if(op[i][0]==1){x=lower(x),n++;f[n]=n,ins(T[n],1,U,x,1,L[x]);}if(op[i][0]==2){x=F(x),y=F(y);if(x==y)continue;T[f[x]=y]=merge(T[x],T[y],1,U);}if(op[i][0]==3){x=F(x),y=lower(y),cnt=0;if(y>1)del(T[x],1,U,1,y-1);if(cnt)ins(T[x],1,U,y,cnt,L[y]*cnt);}if(op[i][0]==4){x=F(x),y=lower(y),cnt=0;if(y<U)del(T[x],1,U,y+1,U);if(cnt)ins(T[x],1,U,y,cnt,L[y]*cnt);}if(op[i][0]==5)printf("%d\n",b[kth(T[F(x)],y)]);if(op[i][0]==6)puts(s[T[F(x)]]>s[T[F(y)]]?"1":"0");if(op[i][0]==7)printf("%d\n",v[T[F(x)]]);}return 0;
}