线段树套trie+可持久化trie or 分治
分治的做法比较神,还没看,先讲讲数据结构。
对于特殊商品,肯定是可持久化trie来搞。
对于其他商品,对商店1~n建线段树,每个节点下建trie树,维护数字出现的最迟时间即可。
然而我被卡内存了,在别的OJ上过了,就当能过吧。。。
#include<cstdio>
#define N 100005
#define ll long long
using namespace std;
namespace ziqian
{
const int INF = 1<<29;
int mecnt, timer, pcnt;
struct node
{
node *ch[2];
int v;
}*trie[N],*null,me[N*300],*root[N*15],*pool[N*15];
int in()
{
register int r = 0;
register char c = getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')r=r*10+c-'0',c=getchar();
return r;
}
void init()
{
null = &me[++mecnt];
null->ch[0] = null->ch[1] = null;
null->v = 0;
trie[0] = null;
root[0] = null;
}
void inser_trie(node *x, node *y, int val)
{
for(int i = 31; i>=0; i--)
{
int v = ((val>>i)&1);
y->ch[v^1] = x->ch[v^1];
y->ch[v] = &me[++mecnt];
y->ch[v]->v = x->ch[v]->v+1;
y = y->ch[v];
x = x->ch[v];
}
}
void inser_trie(node *x, int val)
{
for(int i = 31; i>=0; i--)
{
int v = (val>>i)&1;
if(x->ch[v] == null)
{
x->ch[v] = &me[++mecnt];
*x->ch[v] = *null;
}
x->ch[v]->v = timer;
x = x->ch[v];
}
}
void inser_seg(int x, int l, int r, int pos, int val)
{
inser_trie(root[x], val);
if(l==r)return;
int mid = (l+r)>>1;
if(pos <= mid)inser_seg(x<<1,l,mid,pos,val);
else inser_seg(x<<1|1,mid+1,r,pos,val);
}
void build(int x, int l, int r)
{
root[x] = &me[++mecnt];
*root[x] = *null;
if(l == r)return;
int mid = (l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
void fetch(int x, int l, int r, int ql, int qr)
{
if(ql<=l&&r<=qr)
{
pool[++pcnt] = root[x];
return;
}
int mid = (l+r)>>1;
if(ql <= mid)fetch(x<<1,l,mid,ql,qr);
if(mid < qr)fetch(x<<1|1,mid+1,r,ql,qr);
}
void main()
{
int n=in(), m=in();;
init();
for(int i = 1, a; i <= n; i++)
{
a=in();
trie[i] = &me[++mecnt];
inser_trie(trie[i-1],trie[i],a);
}
build(1,1,n);
for(int i = 1, opt, a, b, c, d; i <= m; i++)
{
opt=in();
if(opt == 0)
{
a=in(),b=in();
++timer;
inser_seg(1, 1, n, a, b);
}
else
{
a=in(),b=in(),c=in(),d=in();
pcnt = 0;
fetch(1,1,n,a,b);
node *x = trie[a-1], *y = trie[b];
ll ans = 0;
for(int k = 31; k>=0; k--)
{
bool found = 0;
int v = ((c>>k)&1)^1;
if(y->ch[v]->v - x->ch[v]->v > 0)
found = 1;
for(int j = 1; j <= pcnt && !found; j++)
{
if(pool[j] -> ch[v] -> v > timer - d)
found = 1;
}
if(found)ans += 1ll<<k;
x=x->ch[found?v:(v^1)];
y=y->ch[found?v:(v^1)];
for(int j = 1; j <= pcnt; j++)
pool[j]=pool[j]->ch[found?v:(v^1)];
}
printf("%lld\n",ans);
}
}
}
}
int main()
{
ziqian::main();
}