将所有权值离散化,建立权值线段树,维护区间内数字个数以及对数的和,用于比较乘积大小。
对于每个连通块维护一棵权值线段树,合并时用线段树合并。
对于操作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; }