[HEOI2013]ALO 【可持久化Trie】

[HEOI2013]ALO
从小到大枚举能量次大的宝石(i),令在它之前的第一个能量大于它的宝石在(l_1),第二个在(l_2),同理设(r_1,r_2)
([l_2+1, r_1-1])([l_1+1, r_2-1])包含了所有可能使(i)作为能量次大宝石的区间
(l_1, l_2, r_1, r_2)用链表,从小到大枚举(i),计算过(i)后把它从链表中去掉,剩下的一定都是比(i+1)能量大的宝石(不包括(i+1)

void ins(int i, int o, int p, int v, int now){
	if(now < 0) {val[o]=i; return ;}
	int k=v>>now&1; if(p) ch[o][k^1]=ch[p][k^1];
	ch[o][k]=++cnt; ins(i, ch[o][k], ch[p][k], v, now-1);
	val[o]=max(val[ch[o][0]], val[ch[o][1]]);
}
int query(int L, int o, int now, int x){
	if(now < 0) return a[val[o]]^x;
	int k=x>>now&1; 
	if(val[ch[o][k^1]] >= L) return query(L, ch[o][k^1], now-1, x);
	return query(L, ch[o][k], now-1, x);
}
bool cmp(int x, int y){return a[x] < a[y];}
void solve(){
	n=read(); 
	for(int i=1; i <= n; i++) a[i]=read(), 
		pk[i]=i, pre[i]=i-1, nxt[i]=i+1, 
		rt[i]=++cnt, ins(i, rt[i], rt[i-1], a[i], 30);
	sort(pk+1, pk+1+n, cmp); int res=0;
	for(int i=1; i < n; i++){
		int x=pk[i], l=pre[x], r=nxt[x], ans=0; nxt[l]=nxt[x], pre[r]=pre[x];
		if(l) ans=max(ans, query(pre[l]+1, rt[r-1], 30, a[x]));
		if(r <= n) ans=max(ans, query(l+1, rt[nxt[r]-1], 30, a[x]));
		res=max(res, ans);
	}
	printf("%d", res);
}
原文地址:https://www.cnblogs.com/zerolt/p/9295487.html