可持续字典树
可持续字典树
题意:求区间内从一点开始到结尾的异或值最大
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=600010;
const int M=N*25;
int n,m;
int s[N];
int tr[M][2];
int mxa_id[M];
int root[N];
int idx;
void inset(int i,int k,int p,int q)//i 下标 k当前处理到第几位 P上一个版本 q当前版本
{
if(k<0)
{
mxa_id[q]=i;
return ;
}
int v=s[i]>>k&1;
if(p)
{
tr[q][v^1]=tr[p][v^1];//将上个版本复制过来
}
tr[q][v]=++idx;
inset(i,k-1,tr[p][v],tr[q][v]);
mxa_id[q]=max(mxa_id[tr[q][0]],mxa_id[tr[q][1]]);
}
int query(int root,int c,int l)//查询最大异或值
{
int p=root;
for(int i=23; i>=0; i--)
{
int v=c>>i&1;
if (mxa_id[tr[p][v ^ 1]] >= l)
p = tr[p][v ^ 1];
else
{
p=tr[p][v];
}
}
return c^s[mxa_id[p]];
}
int main()
{
cin>>n>>m;
mxa_id[0]=-1;
root[0]=++idx;
inset(0,23,0,root[0]);
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&x);
s[i]=s[i-1]^x;
root[i]=++idx;
inset(i,23,root[i-1],root[i]);
}
char op[2];
int l,r,x;
while(m--)
{
scanf("%s", op);
if(*op=='A')
{
scanf("%d",&x);
n++;
s[n]=s[n-1]^x;//前缀和加速
root[n]=++idx;
inset(n,23,root[n-1],root[n]);
}
else
{
scanf("%d%d%d", &l, &r, &x);
printf("%d\n", query(root[r - 1], s[n] ^ x, l - 1));
}
}
return 0;
}
可持续线段树
求区间第K大的数
注:root[r]-root[l-1]等于再次期间内添加了多少个数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=1e5+10;
int n,m;
int a[N];
vector<int> v;
struct node
{
int l,r;
int cnt;//存储区间内有几个数
}tree[22*N];
int root[N],tot;//记录版本
int finds(int x)//二分查找离散化后的下标
{
return lower_bound(v.begin(), v.end(), x) - v.begin();
}
int build(int l,int r)//建树
{
int p=++tot;
if(l==r)
{
return p;
}
int mid=(l+r)/2;
tree[p].l=build(l,mid);
tree[p].l=build(mid+1,r);
return p;
}
int inset(int u,int l,int r,int k)//插入修改区间数的个数
{
int q=++tot;
tree[q]=tree[u];
if(l==r)
{
tree[q].cnt++;
return q;
}
int mid=(l+r)/2;
if(k>mid)
{
tree[q].r=inset(tree[u].r,mid+1,r,k);
}
else
{
tree[q].l=inset(tree[u].l,l,mid,k);
}
tree[q].cnt=tree[tree[q].l].cnt+tree[tree[q].r].cnt;
return q;
}
int query(int q,int p,int l,int r,int k)//查询第K大的数
{
if(l==r)
{
return r;
}
int cnt=tree[tree[q].l].cnt-tree[tree[p].l].cnt;
int mid=(l+r)/2;
if(k<=cnt)
{
return query(tree[q].l,tree[p].l,l,mid,k);
}
else
{
return query(tree[q].r,tree[p].r,mid+1,r,k-cnt);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
root[0]=build(0,v.size()-1);
for(int i=1;i<=n;i++)
{
root[i]=inset(root[i-1],0,v.size()-1,finds(a[i]));
}
while(m--)
{
int l,r,k;
cin>>l>>r>>k;
cout<<v[query(root[r],root[l-1],0,v.size()-1,k)]<<endl;//query查询的是离散化后的下标
}
return 0;
}