题目描述:
现在你拥有 n 颗宝石,每颗宝石有一个能量密度,记为 ai,这些宝石的能量 密度两两不同。现在你可以选取连续的一些宝石(必须多于一个)进行融合,设 为 ai, ai+1, …, aj,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值 与其他任意一颗宝石的能量密度按位异或的值,即,设该段宝石能量密度次大值 为 k,则生成的宝石的能量密度为 max{k xor ap | ap ≠ k , i ≤ p ≤ j}
题解:
首先建可持久化Trie。然后是区间的选取问题。
想了好久想出来一种方法:
对于每个点建双向链表,从小到大删点。
对于每个点可取区间为[左方第二个比它大的+1,右方第二个比它大的-1]。
代码:
#include#include #include using namespace std;#define N 50050inline int rd(){ int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c;}int n,a[N];struct Trie{ int tot,siz[32*N],ch[32*N][2],rt[N]; void insert(int k,int x) { int u,l=rt[k-1]; rt[k]=u=++tot; for(int i=30;i>=0;i--) { ch[u][0]=ch[l][0],ch[u][1]=ch[l][1],siz[u]=siz[l]+1; int k = (x>>i)&1; ch[u][k]=++tot; u=ch[u][k],l=ch[l][k]; } siz[u]=siz[l]+1; } int query(int l,int r,int x) { l = rt[l],r = rt[r]; int ret = 0; for(int i=30;i>=0;i--) { int k = (x>>i)&1; if(siz[ch[r][!k]]-siz[ch[l][!k]]) { l=ch[l][!k],r=ch[r][!k]; ret|=(1<