高级数据结构模板

可持久化并查集[BZOJ3673]


#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int N=2e4*20;
int lc[N],rc[N],fa[N],root[N],size[N],tot,n,m,op,k,a,b;
void build(int &o,int L,int R){
	o=++tot;
	if(L==R){
		fa[o]=L;return;
	}
	int M=L+R>>1;
	build(lc[o],L,M);
	build(rc[o],M+1,R);
}
void add(int o,int L,int R,int x){
	if(L==R){
		size[o]++;return;
	}
	int M=L+R>>1;
	if(x<=M)add(lc[o],L,M,x);
	else add(rc[o],M+1,R,x);
}
void modify(int &o,int L,int R,int last,int a,int b){
	o=++tot;
	if(L==R){
		fa[o]=b,size[o]=size[last];
		return;
	}
	int M=L+R>>1;
	lc[o]=lc[last],rc[o]=rc[last];
	if(a<=M)modify(lc[o],L,M,lc[last],a,b);
	else modify(rc[o],M+1,R,rc[last],a,b);
}
int query(int o,int L,int R,int p){
	if(L==R)return o;
	int M=L+R>>1;
	if(p<=M)query(lc[o],L,M,p);
	else query(rc[o],M+1,R,p);
}
int find(int root,int x){
	int p=query(root,1,n,x);
	if(x==fa[p])return p;//attention
	return find(root,fa[p]);
}
int main()
{
	//freopen("a.in","r",stdin);
	scanf("%d%d",&n,&m);
	build(root[0],1,n);
	rep(i,1,m){
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d",&a,&b);
			root[i]=root[i-1];
			int p=find(root[i],a);
			int q=find(root[i],b);
			if(fa[p]==fa[q])continue;
			if(size[p]>size[q])swap(p,q);
			modify(root[i],1,n,root[i-1],fa[p],fa[q]);
			if(size[p]!=size[q])add(root[i],1,n,fa[q]);
		}else if(op==2){
			scanf("%d",&k);
			root[i]=root[k];
		}else {
			scanf("%d%d",&a,&b);
			root[i]=root[i-1];
			int p=find(root[i],a);
			int q=find(root[i],b);
			if(fa[p]==fa[q])puts("1");
			else puts("0");
		}
	}return 0;
}

树套树[BZOJ3196]


//BIT套动态开点权值线段树
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N=5e4+10;
const int inf=1e8;
int ch[N*200][2],v[N*200],root[N],num[N],tmp1[N],tmp2[N],tot=0,x,a,b,c,d,n,m;
inline int lowbit(int x){return x&-x;}
void add(int &o,int L,int R,int x,int p){
	if(!o)o=++tot;
	if(L==R)v[o]+=p;
	else{
		int M=L+R>>1;
		if(x<=M)add(ch[o][0],L,M,x,p);
		else add(ch[o][1],M+1,R,x,p);
		v[o]=v[ch[o][0]]+v[ch[o][1]];
	}
}
void change(int x,int p){
	int tmp=num[x];
	for(;x<=N;x+=lowbit(x)){
		if(tmp!=-1)add(root[x],0,inf,tmp,-1);
		add(root[x],0,inf,p,1);
	}
}
bool pushdown(int L,int R,int k){
	bool ans=0;
	for(;R;R-=lowbit(R))tmp1[R]=ch[tmp1[R]][k],ans|=tmp1[R];
	for(;L;L-=lowbit(L))tmp2[L]=ch[tmp2[L]][k],ans|=tmp2[L];
	return ans;
}
void reset(int L,int R){
	for(int i=R;i;i-=lowbit(i))tmp1[i]=root[i];
	for(int i=L;i;i-=lowbit(i))tmp2[i]=root[i];
}
int query1(int L,int R,int ql,int qr,int k){
	if(k<0||L==R)return 1;
	int M=L+R>>1;
	if(k<=M){
		if(!pushdown(ql,qr,0))return 1;
		return query1(L,M,ql,qr,k);
	}else{
		int w=0;
		for(int i=qr;i;i-=lowbit(i))w+=v[ch[tmp1[i]][0]];
		for(int i=ql;i;i-=lowbit(i))w-=v[ch[tmp2[i]][0]];
		if(!pushdown(ql,qr,1))return w+1;
		return w+query1(M+1,R,ql,qr,k);
	}
}
int query2(int L,int R,int ql,int qr,int k){
	if(k<=0)return -1;
	int w=0;
	for(int i=qr;i;i-=lowbit(i))w+=v[tmp1[i]];
	for(int i=ql;i;i-=lowbit(i))w-=v[tmp2[i]];
	if(w<k)return -1;
	if(L==R)return L;
	int M=L+R>>1;w=0;
	for(int i=qr;i;i-=lowbit(i))w+=v[ch[tmp1[i]][0]];
	for(int i=ql;i;i-=lowbit(i))w-=v[ch[tmp2[i]][0]];
	if(k<=w){
		pushdown(ql,qr,0);
		return query2(L,M,ql,qr,k);
	}else{
		pushdown(ql,qr,1);
		return query2(M+1,R,ql,qr,k-w);
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	memset(num,-1,sizeof(num));
	rep(i,1,n){scanf("%d",&x);change(i,x);num[i]=x;}
	while(m--){
		scanf("%d%d%d",&a,&b,&c);
		if(a==3){change(b,c);num[b]=c;}
		else{
			scanf("%d",&d);
			if(a==1){
				reset(b-1,c);
				printf("%d\n",query1(0,inf,b-1,c,d));
			}
			if(a==2){
				reset(b-1,c);
				printf("%d\n",query2(0,inf,b-1,c,d));
			}
			if(a==4){
				reset(b-1,c);
				int rk=query1(0,inf,b-1,c,d);
                                reset(b-1,c);
                                if(rk==1) printf("fuck\n");
                                else printf("%d\n",query2(0,inf,b-1,c,rk-1));
			}
			if(a==5){
				reset(b-1,c);
                                int rk=query1(0,inf,b-1,c,d+1);
                                reset(b-1,c);
                                int re=query2(0,inf,b-1,c,rk);
                                if(re==-1) printf("fuck\n");
                                else printf("%d\n",re);
			}
		}
	}return 0;
}

少女填坑中...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值