bzoj3217 ALOEXT 替罪羊树套trie

15 篇文章 0 订阅
10 篇文章 0 订阅

Description


给定一个序列,要求兹磁一下操作

  1. 插入一个数
  2. 删除一个数
  3. 修改一个数
  4. 查询区间次大值与另一数字异或的最大值

Solution


都是套路。。真·oi中的解析几何

唯一需要注意的就是替罪羊树上删除只打标记,我们重构的时候才真正删除,并且我写的做法需要同时维护包含删除节点的s和不包含删除节点的size,根据s判断是否重构

我也就写了6k+,我爱数据结构.jpg

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <stack>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)

const double alpha=0.8;
const int N=600005;

int w[N],tot;

namespace Trie {
	struct treeNode {
		int son[2],size;
	} t[30000005];
	std:: stack <int> stack;
	int tot;

	int new_node() {
		if (stack.empty()) return ++tot;
		int x=stack.top(); stack.pop();
		return x;
	}

	void reuse(int x) {
		if (t[x].son[0]) reuse(t[x].son[0]);
		if (t[x].son[1]) reuse(t[x].son[1]);
		t[x].son[0]=t[x].son[1]=t[x].size=0;
		stack.push(x);
	}

	void ins(int &root,int v,int s) {
		if (!root) root=new_node();
		int x=root; t[x].size+=s;
		drp(i,19,0) {
			int k=((v>>i)&1);
			if (!t[x].son[k]) t[x].son[k]=new_node();
			x=t[x].son[k];
			t[x].size+=s;
		}
	}

	int ask(int root,int v) {
		int x=root,res=0;
		drp(i,19,0) {
			int k=((v>>i)&1);
			if (t[t[x].son[!k]].size) x=t[x].son[!k],res+=(1<<i);
			else x=t[x].son[k];
		}
		return res;
	}
}

namespace Scape {
	struct treeNode {
		int son[2],size,s,fa,del,mx1,mx2;
	} t[N];
	std:: vector <int> p,q,u;
	int rt[N],vec[N],R,root;

	bool cmp(int x,int y) {
		return x>y;
	}

	void push_up(int x) {
		t[x].size=!t[x].del; u.clear();
		t[x].s=1;
		int ls=t[x].son[0],rs=t[x].son[1];
		if (ls) {
			t[x].s+=t[ls].s;
			t[x].size+=t[ls].size;
			u.push_back(t[ls].mx1);
			u.push_back(t[ls].mx2);
		}
		if (rs) {
			t[x].s+=t[rs].s;
			t[x].size+=t[rs].size;
			u.push_back(t[rs].mx1);
			u.push_back(t[rs].mx2);
		}
		u.push_back(w[x]); u.push_back(0);
		std:: sort(u.begin(), u.end(),cmp);
		t[x].mx1=u[0]; t[x].mx2=u[1];
	}

	void ins(int x,int k,int nw) {
		Trie:: ins(rt[x],w[nw],1);
		int tmp=t[t[x].son[0]].size+(!t[x].del);
		if (tmp>=k) {
			if (!t[x].son[0]) {
				t[x].son[0]=nw; t[nw].fa=x; t[nw].size=1;
				t[nw].mx1=w[nw]; t[nw].mx2=0;
				Trie:: ins(rt[nw],w[nw],1);
			} else ins(t[x].son[0],k,nw);
		} else {
			if (!t[x].son[1]) {
				t[x].son[1]=nw; t[nw].fa=x; t[nw].size=1;
				t[nw].mx1=w[nw]; t[nw].mx2=0;
				Trie:: ins(rt[nw],w[nw],1);
			} else ins(t[x].son[1],k-tmp,nw);
		}
		if (t[x].fa&&t[x].s>alpha*t[t[x].fa].s) R=t[x].fa;
		push_up(x);
	}

	int del(int x,int k) {
		int tmp=t[t[x].son[0]].size,wjp;
		if (!t[x].del) {
			if (tmp+1==k) {
				Trie:: ins(rt[x],w[x],-1);
				wjp=w[x]; w[x]=0;
				t[x].del=1;
				push_up(x); return wjp;
			} else if (tmp>=k) wjp=del(t[x].son[0],k);
			else wjp=del(t[x].son[1],k-tmp-1);
		} else {
			if (tmp>=k) wjp=del(t[x].son[0],k);
			else wjp=del(t[x].son[1],k-tmp);
		}
		Trie:: ins(rt[x],wjp,-1);
		if (t[x].fa&&t[x].s>alpha*t[t[x].fa].s) R=t[x].fa;
		push_up(x);
		return wjp;
	}

	int modify(int x,int k,int v) {
		Trie:: ins(rt[x],v,1);
		int tmp=t[t[x].son[0]].size,wjp;
		if (!t[x].del) {
			if (tmp+1==k) {
				Trie:: ins(rt[x],w[x],-1);
				wjp=w[x]; w[x]=v;
				push_up(x); return wjp;
			} else if (tmp>=k) wjp=modify(t[x].son[0],k,v);
			else wjp=modify(t[x].son[1],k-tmp-1,v);
		} else {
			if (tmp>=k) wjp=modify(t[x].son[0],k,v);
			else wjp=modify(t[x].son[1],k-tmp,v);
		}
		Trie:: ins(rt[x],wjp,-1);
		push_up(x);
		return wjp;
	}

	void dfs(int x) {
		Trie:: reuse(rt[x]); rt[x]=0;
		if (t[x].son[0]) dfs(t[x].son[0]);
		if (!t[x].del) vec[++vec[0]]=x;
		if (t[x].son[1]) dfs(t[x].son[1]);
	}

	int build(int l,int r) {
		int mid=(l+r)>>1;
		int x=vec[mid]; t[x].fa=t[x].del=0;
		t[x].son[0]=t[x].son[1]=0;
		if (l!=mid) t[x].son[0]=build(l,mid-1),t[t[x].son[0]].fa=x;
		if (mid!=r) t[x].son[1]=build(mid+1,r),t[t[x].son[1]].fa=x;
		rep(i,l,r) Trie:: ins(rt[x],w[vec[i]],1);
		push_up(x); return x;
	}

	void rebuild() {
		int ff=t[R].fa,k=(t[ff].son[1]==R);
		vec[0]=0; dfs(R); R=0;
		if (!vec[0]) {
			if (ff) t[ff].son[k]=0;
			else root=0;
			return ;
		}
		int mid=build(1,vec[0]);
		if (ff) {
			t[ff].son[k]=mid;
			t[mid].fa=ff;
		} else root=mid;
	}

	void get(int x,int l,int r) {
		if (r<l) return ;
		if (l==1&&r==t[x].size) {
			q.push_back(x); return ;
		}
		int a=t[t[x].son[0]].size;
		if (!t[x].del&&l<=a+1&&r>=a+1) p.push_back(x);
		get(t[x].son[0],l,std:: min(a,r));
		get(t[x].son[1],std:: max(1,l-a-!t[x].del),r-a-!t[x].del);
	}

	int solve(int l,int r) {
		int ans=0,mx1=0,mx2=0;
		p.clear(); q.clear();
		get(root,l,r);
		for (int i=0;i<q.size();++i) {
			u.clear();
			if (t[q[i]].mx1>mx1) mx2=std:: max(mx1,t[q[i]].mx2),mx1=t[q[i]].mx1;
			else if (t[q[i]].mx1>mx2) mx2=t[q[i]].mx1;
		}
		for (int i=0;i<p.size();++i) {
			u.clear();
			if (w[p[i]]>mx1) mx2=mx1,mx1=w[p[i]];
			else if (w[p[i]]>mx2) mx2=w[p[i]];
		}
		for (int i=0;i<p.size();++i) ans=std:: max(ans,mx2^w[p[i]]);
		for (int i=0;i<q.size();++i) ans=std:: max(ans,Trie:: ask(rt[q[i]],mx2));
		return ans;
	}

	void debug(int x) {
		if (t[x].son[0]) debug(t[x].son[0]);
		if (!t[x].del) printf("%d ", w[x]);
		if (t[x].son[1]) debug(t[x].son[1]);
	}
} ;

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

int main(void) {
	int n=read(),m=read(); tot=n;
	rep(i,1,n) {
		w[i]=read();
		Scape:: vec[++Scape:: vec[0]]=i;
	}
	Scape:: root=Scape:: build(1,Scape:: vec[0]);
	for (int opt,lastans=0,n0=n;m--;) {
		for (opt=getchar();opt<'A'||opt>'Z';) opt=getchar();
		int x=(read()+lastans)%n0+1;
		if (opt=='I') {
			int y=(read()+lastans)%1048576;
			w[++tot]=y; n0++;
			Scape:: ins(Scape:: root,x,tot);
		} else if (opt=='D') { n0--;
			Scape:: del(Scape:: root,x);
		} else if (opt=='C') {
			int y=(read()+lastans)%1048576;
			Scape:: modify(Scape:: root,x,y);
		} else {
			int y=(read()+lastans)%n0+1;
			lastans=Scape:: solve(x,y);
			printf("%d\n", lastans);
		}
		if (Scape:: R) Scape:: rebuild();
		// Scape:: debug(Scape:: root); puts("");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值