《算法竞赛进阶指南》 0x45 ~ 0x48 代码 + 杂谈

点分治

///淀粉质
链接 : https://blog.csdn.net/qq_40831340/article/details/90234372

平衡树

theap 模板

// treap模板题
// 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
//插入x数
//删除x数(若有多个相同的数,因只删除一个)
//查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
//查询排名为x的数
//求x的前驱(前驱定义为小于x,且最大的数)
//求x的后继(后继定义为大于x,且最小的数)
const int maxn = 100000+5;
const int INF = 0x3f3f3f3f;
int siz[maxn];
int s[maxn][3];
int w[maxn],pos[maxn];
int tot;

void up(int i) {siz[i]=siz[s[i][0]]+siz[s[i][1]]+1;}

void spin(int &i,int p) {
	int t=s[i][p];
	s[i][p]=s[t][!p],s[t][!p]=i,up(i),up(t),i=t;
}

void ins(int x,int &i) {
	if(!i) {
		i=++tot,siz[i]=1,w[i]=x,pos[i]=rand();
		return;
	}
	siz[i]++;
	if(x<=w[i]) {
		ins(x,s[i][0]);
		if(pos[s[i][0]]<pos[i])spin(i,0);
	} else {
		ins(x,s[i][1]);
		if(pos[s[i][1]]<pos[i])spin(i,1);
	}
}

void del(int x,int &i) {
	if(w[i]==x) {
		if(s[i][0]*s[i][1]==0) {
			i=s[i][0]+s[i][1];
			return;
		}
		if(pos[s[i][0]]>pos[s[i][1]]) {
			spin(i,1);
			del(x,s[i][0]);
		} else {
			spin(i,0);
			del(x,s[i][1]);
		}
	} else if(w[i]>x)del(x,s[i][0]);
	else del(x,s[i][1]);
	up(i);
}

int find(int x,int i) {
	if(!i)return 1;
	if(w[i]>=x)return find(x,s[i][0]);
	return find(x,s[i][1])+siz[s[i][0]]+1;
}

int ask(int x,int i) {
	if(siz[s[i][0]]==x-1)return w[i];
	if(siz[s[i][0]]>=x)return ask(x,s[i][0]);
	return ask(x-siz[s[i][0]]-1,s[i][1]);
}

int pre(int x,int i) {
	if(!i)return -INF;
	if(w[i]<x)return max(w[i],pre(x,s[i][1]));
	else return pre(x,s[i][0]);
}
int nxt(int x,int i) {
	if(!i)return INF;
	if(w[i]>x)return min(w[i],nxt(x,s[i][0]));
	else return nxt(x,s[i][1]);
}

signed main() {
	cin>>n;
	int root=0;
	while(n--) {
		int cmd;
		cin>>cmd;
		if(cmd==1) cin>>m,ins(m,root);
		if(cmd==2) cin>>m,del(m,root);
		if(cmd==3) cin>>m,cout<<find(m,root)<<endl;
		if(cmd==4) cin>>m,cout<<ask(m,root)<<endl;
		if(cmd==5) cin>>m,cout<<pre(m,root)<<endl;
		cmd==6;
		cin>>m,cout<<nxt(m,root)<<endl;
	}
	return 0;
}

可持续化
链接 https://blog.csdn.net/qq_40831340/article/details/90733094

#include <iostream>
#include <cstdio>
using namespace std;
const signed maxn =  600000+10;
signed trie[maxn * 24][2], latest[maxn * 24];
signed s[maxn], root[maxn], n, m, tot;
inline void ins(int i, int k, int p, int q){
	if(k < 0) {
		latest[q] = i;
		return ;
	}
	int c = s[i] >> k & 1;
	if(p) trie[q][c ^ 1] = trie[p][c ^ 1];
	trie[q][c] = ++tot;
	ins(i, k-1, trie[p][c], trie[q][c]);
	latest[q] = max (latest[trie[q][0]], latest[trie[q][1]]); 
}
signed ask(int now, int val, int k, int limit) {
	if(k < 0) return s[latest[now]] ^ val;
	int c = val >> k & 1;
	if(latest[trie[now][c ^ 1]] >= limit)
		return ask(trie[now][c ^ 1], val, k - 1, limit);
	else 
		return ask(trie[now][c], val, k - 1, limit);
} 
signed main(){
	scanf("%d %d",&n,&m);
	latest[0] = -1;
	root[0] = ++tot;
	ins(0, 23, 0, root[0]);
	int x;
	for(int i = 1; i <= n ; i ++ ) {
		scanf("%d",&x);
		s[i] = x ^ s[i - 1];
		root[i] = ++ tot;
		ins(i, 23, root[i - 1], root[i]);
	}
	for(int i = 1; i <= m; i ++) {
		int l, r;
		char cmd[2];
		scanf("%s",cmd);
		if(cmd[0] == 'A') {
			scanf("%d",&x);
			root[++n] = ++ tot;
			s[n] = s[n - 1] ^ x;
			ins(n, 23, root[n - 1], root[n]);
		}else{
			scanf("%d %d %d",&l, &r,&x);
			cout << ask(root[r - 1], x ^ s[n], 23, l - 1) << endl;
		}
	}
	return 0;
}
全部评论

相关推荐

10-27 17:26
东北大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务