题解 [CF1100F] Ivan and Burgers
是猫树分治的板子题
但是直接扫描线比猫树分治少个 log
直接猫树合并的话复杂度 \(O(n\log^2 n)\)
- 注意使用
lcp(x, y)=x>>lg[x^y]
时 \(x, y\) 都是线段树上的节点编号
也就是说如果下标从 0 开始的话这里的节点编号应该是 \(l+bln, r+bln\) - 注意用猫树时原序列之类的东西都要开两倍空间
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 500010
#define pb push_back
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, q;
int a[N<<1], lg[N<<1], ans[N], bln;
struct tpl{int l, r, id;};
vector<tpl> que[N<<2];
struct basic{
int base[21];
basic(){memset(base, 0, sizeof(base));}
void insert(int t) {
for (int i=20; ~i; --i) if (t&(1<<i)) {
if (!base[i]) {base[i]=t; return ;}
else t^=base[i];
}
}
int qmax() {
int ans=0;
for (int i=20; ~i; --i) if ((ans^base[i])>ans) ans^=base[i];
return ans;
}
void clear() {memset(base, 0, sizeof(base));}
}pre[N<<1], suf[N<<1], tem;
basic merge(basic a, basic b) {
basic ans=a;
for (int i=0; i<=20; ++i) if (b.base[i]) ans.insert(b.base[i]);
return ans;
};
int tl[N<<2], tr[N<<2];
#define tl(p) tl[p]
#define tr(p) tr[p]
void build(int p, int l, int r) {
// cout<<"build: "<<p<<' '<<l<<' '<<r<<endl;
tl(p)=l; tr(p)=r;
if (l==r) return ;
int mid=(l+r)>>1;
for (int i=l; i<=r; ++i) pre[i].clear(), suf[i].clear();
suf[mid].insert(a[mid]);
for (int i=mid-1; i>=l; --i) suf[i]=suf[i+1], suf[i].insert(a[i]);
for (int i=mid+1; i<=r; ++i) pre[i]=pre[i-1], pre[i].insert(a[i]);
for (auto it:que[p]) {
tem=merge(suf[it.l], pre[it.r]);
ans[it.id]=tem.qmax();
}
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
signed main()
{
n=read();
for (int i=0; i<n; ++i) a[i]=read();
for (bln=1; bln<n; bln<<=1) ;
// cout<<"bln: "<<bln<<endl;
for (int i=1; i<=bln; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
q=read();
for (int i=1,l,r; i<=q; ++i) {
l=read()-1; r=read()-1;
if (l==r) ans[i]=a[l];
else que[(l+bln)>>lg[(l+bln)^(r+bln)]].pb({l, r, i});
}
build(1, 0, bln-1);
for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
return 0;
}