传送门
线段树合并菜题(然而 f i n d find find函数写错位置调了好久)
支持的操作题目写的很清楚了,然后有一个神奇的限制 c ≤ 7 c\le7 c≤7要注意到不然会去想毒瘤线段树的做法。
思路:
这题只有一个新奇的操作就是比较两个连通块的所有点权的乘积的大小。
这个东西可以对所有点权取对数之后转化为比较加和的大小。
剩下的都可以用并查集+线段树合并秒掉。
注意题目卡空间
代码:
#include
#define lc (son[p][0])
#define rc (son[p][1])
#define ri register int
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
const int N=4e5+5;
struct Npde{int op,a,b;}qry[N];
int son[N*18][2],siz[N*18],tot=0,rt[N],fa[N],mp[N],n,m,cnt=0;
double val[N*18];
bool tag[N*18];
inline void pushup(int p){siz[p]=siz[lc]+siz[rc],val[p]=val[lc]+val[rc];}
inline void pushnow(int p){val[p]=siz[p]=0,tag[p]=1;}
inline void pushdown(int p){if(tag[p])pushnow(lc),pushnow(rc),tag[p]=0;}
inline void build(int&p,int l,int r,int k,int v1,double v2){
if(!p)p=++tot;
if(l==r){siz[p]=v1,val[p]=v2;return;}
int mid=l+r>>1;
pushdown(p);
k<=mid?build(lc,l,mid,k,v1,v2):build(rc,mid+1,r,k,v1,v2);
pushup(p);
}
inline int merge(int x,int y,int l,int r){
if(!x||!y)return x+y;
siz[x]+=siz[y],val[x]+=val[y];
if(l==r)return x;
int mid=l+r>>1;
pushdown(x),pushdown(y);
son[x][0]=merge(son[x][0],son[y][0],l,mid);
son[x][1]=merge(son[x][1],son[y][1],mid+1,r);
return x;
}
inline int query(int p,int l,int r,int ql,int qr){
if(!p||ql>r||qr<l)return 0;
if(ql<=l&&r<=qr)return siz[p];
int mid=l+r>>1;
pushdown(p);
if(qr<=mid)return query(lc,l,mid,ql,qr);
if(ql>mid)return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,mid)+query(rc,mid+1,r,mid+1,qr);
}
inline void update(int p,int l,int r,int ql,int qr){
if(!p||ql>r||qr<l)return;
if(ql<=l&&r<=qr)return pushnow(p);
int mid=l+r>>1;
pushdown(p);
if(qr<=mid)update(lc,l,mid,ql,qr);
else if(ql>mid)update(rc,mid+1,r,ql,qr);
else update(lc,l,mid,ql,mid),update(rc,mid+1,r,mid+1,qr);
pushup(p);
}
inline int ask(int p,int l,int r,int k){
if(l==r)return l;
int mid=l+r>>1;
pushdown(p);
if(siz[lc]>=k)return ask(lc,l,mid,k);
return ask(rc,mid+1,r,k-siz[lc]);
}
inline int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);}
inline int idx(int x){return lower_bound(mp+1,mp+n+1,x)-mp;}
int main(){
m=read();
for(ri i=1;i<=m;++i){
qry[i].op=read(),qry[i].a=read();
if(qry[i].op!=1&&qry[i].op!=7)qry[i].b=read();
if(qry[i].op==1)mp[++n]=qry[i].a;
if(qry[i].op==3||qry[i].op==4)mp[++n]=qry[i].b;
}
sort(mp+1,mp+n+1),n=unique(mp+1,mp+n+1)-mp-1;
for(ri i=1;i<=m;++i){
switch(qry[i].op){
case 1:build(rt[++cnt],1,n,idx(qry[i].a),1,log2(qry[i].a)),fa[cnt]=cnt;break;
case 2:{
int fx=find(qry[i].a),fy=find(qry[i].b);
if(fx^fy)fa[fy]=fx,rt[fx]=merge(rt[fx],rt[fy],1,n);
break;
}
case 3:{
int fx=find(qry[i].a);
int p=idx(qry[i].b),s=query(rt[fx],1,n,1,p);
update(rt[fx],1,n,1,p),build(rt[fx],1,n,p,s,s*log2(qry[i].b));
break;
}
case 4:{
int fx=find(qry[i].a);
int p=idx(qry[i].b),s=query(rt[fx],1,n,p,n);
update(rt[fx],1,n,p,n),build(rt[fx],1,n,p,s,s*log2(qry[i].b));
break;
}
case 5:cout<<mp[ask(rt[find(qry[i].a)],1,n,qry[i].b)]<<'\n';break;
case 6:cout<<(val[rt[find(qry[i].a)]]>val[rt[find(qry[i].b)]])<<'\n';break;
case 7:cout<<siz[rt[find(qry[i].a)]]<<'\n';break;
}
}
return 0;
}