【BZOJ4399】—膜法少女LJJ(线段树合并)

传送门

坑比题面c7c\le 7

考虑到343、4操作可行的只有平衡树或者权值线段树维护
大力上线段树合并
用并查集维护一下联通块
至于权值积转成对数加就可以了

#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;
		}
	}
}
posted @ 2019-04-10 16:59  Stargazer_cykoi  阅读(199)  评论(0编辑  收藏  举报