【BZOJ4399】—膜法少女LJJ(线段树合并)
坑比题面
考虑到操作可行的只有平衡树或者权值线段树维护
大力上线段树合并
用并查集维护一下联通块
至于权值积转成对数加就可以了
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<21|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
const int N=400005;
char x;
struct ask{
short op;
int x,y;
}q[N];
int b[N],fa[N],n,m,cnt,rt[N];
inline int idx(int x){
return lower_bound(b+1,b+cnt+1,x)-b;
}
inline int find(int x){
return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}
namespace Seg{
int lc[N*18],rc[N*18],siz[N*18],tot;
bool cl[N*18];
double val[N*18];
char y;
#define mid ((l+r)>>1)
inline void pushup(int u){
siz[u]=siz[lc[u]]+siz[rc[u]];
val[u]=val[lc[u]]+val[rc[u]];
}
inline void pushnow(int u){
siz[u]=val[u]=0;
cl[u]=1;
}
inline void pushdown(int u){
if(!cl[u])return;
pushnow(lc[u]);
pushnow(rc[u]);
cl[u]=0;
}
void insert(int &u,int l,int r,int p,int si,double k){
if(!u)u=++tot;
if(l==r){siz[u]=si,val[u]=k;return;}
pushdown(u);
if(p<=mid)insert(lc[u],l,mid,p,si,k);
else insert(rc[u],mid+1,r,p,si,k);
pushup(u);
}
void update(int u,int l,int r,int st,int des){
if(!u)return;
if(st<=l&&r<=des){pushnow(u);return;}
pushdown(u);
if(st<=mid)update(lc[u],l,mid,st,des);
if(mid<des)update(rc[u],mid+1,r,st,des);
pushup(u);
}
int query(int u,int l,int r,int st,int des){
if(!u)return 0;
if(st<=l&&r<=des)return siz[u];
int res=0;pushdown(u);
if(st<=mid)res+=query(lc[u],l,mid,st,des);
if(mid<des)res+=query(rc[u],mid+1,r,st,des);
pushup(u);
return res;
}
int merge(int r1,int r2,int l,int r){
if(!r1||!r2)return r1+r2;
val[r1]+=val[r2],siz[r1]+=siz[r2];
if(l==r)return r1;
pushdown(r1),pushdown(r2);
lc[r1]=merge(lc[r1],lc[r2],l,mid);
rc[r1]=merge(rc[r1],rc[r2],mid+1,r);
pushup(r1);return r1;
}
inline int askkth(int u,int l,int r,int k){
if(l==r)return b[l];
pushdown(u);
if(siz[lc[u]]>=k)return askkth(lc[u],l,mid,k);
else return askkth(rc[u],mid+1,r,k-siz[lc[u]]);
}
}
using namespace Seg;
inline void merge(int u,int v){
int f1=find(u),f2=find(v);
if(f1!=f2)fa[f2]=f1,rt[f1]=merge(rt[f1],rt[f2],1,cnt);
}
int main(){
m=read();
for(int i=1;i<=m;i++){
q[i].op=read(),q[i].x=read();
if(q[i].op!=1&&q[i].op!=7)q[i].y=read();
if(q[i].op==3||q[i].op==4)b[++cnt]=q[i].y;
if(q[i].op==1)b[++cnt]=q[i].x;
}
sort(b+1,b+cnt+1),cnt=unique(b+1,b+cnt+1)-b-1;
for(int i=1;i<=m;i++){
switch(q[i].op){
case 1:insert(rt[++n],1,cnt,idx(q[i].x),1,log(q[i].x)),fa[n]=n;break;
case 2:merge(q[i].x,q[i].y);break;
case 3:{
int u=find(q[i].x),k=idx(q[i].y);
int num=query(rt[u],1,cnt,1,k);
update(rt[u],1,cnt,1,k),insert(rt[u],1,cnt,k,num,num*log(q[i].y));
break;
}
case 4:{
int u=find(q[i].x),k=idx(q[i].y);
int num=query(rt[u],1,cnt,k,cnt);
update(rt[u],1,cnt,k,cnt),insert(rt[u],1,cnt,k,num,num*log(q[i].y));
break;
}
case 5:cout<<askkth(rt[find(q[i].x)],1,cnt,q[i].y)<<'\n';break;
case 6:cout<<(val[rt[find(q[i].x)]]>val[rt[find(q[i].y)]])<<'\n';break;
case 7:cout<<siz[rt[find(q[i].x)]]<<'\n';break;
}
}
}