2019.01.16 bzoj4399: 魔法少女LJJ(线段树合并)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/86513142

传送门
线段树合并菜题(然而 f i n d find 函数写错位置调了好久)
支持的操作题目写的很清楚了,然后有一个神奇的限制 c 7 c\le7 要注意到不然会去想毒瘤线段树的做法。


思路:
这题只有一个新奇的操作就是比较两个连通块的所有点权的乘积的大小。
这个东西可以对所有点权取对数之后转化为比较加和的大小。
剩下的都可以用并查集+线段树合并秒掉。
注意题目卡空间
代码:

#include<bits/stdc++.h>
#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;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/86513142
今日推荐