比較は明らかにこの質問を永続的トライすることができ、我々は永続トライ統計的な答えのための特別な商品を向けることができると思います。
添加品とクエリ操作のために、我々は、ツリーラインを維持する、ツリーラインメンテナンスMeike全てトライインデックス番号がこの範囲内トライ内の各ノードのための最大の修正時間を維持しながら、そう一度尋ね頼むその後、トライをログセグメントツリーに対応することができます。時間と空間の複雑\(O(nlog ^ 2n個)\) 。
最適化を考慮ビット高い空間複雑。力で気づいた、我々はすべての操作を尋ねると、上記オフラインに基づいて動作するノードを対応するツリーラインに掛け、その後、トライを持つツリーラインの各ノードのために再びそれを行うことができます。このようなスペースの複雑さがある\(O(nlogn)\)があります。
また、基本的な考え方は同じで、分割統治され、ツリーライン、ツリーラインのための時間をオフにマークすることができます。
#include<bits/stdc++.h>
using namespace std;
int read(){
int a = 0; char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)){a = a * 10 + c - 48; c = getchar();}
return a;
}
const int _ = 1e5 + 7;
namespace Trie{
const int __ = _ * 40;
int ch[__][2] , lst[__] , cnt;
int create(int x){int t = ++cnt; ch[t][0] = ch[x][0]; ch[t][1] = ch[x][1]; lst[t] = lst[x]; return t;}
void ins(int &rt , int t , int x){
rt = create(rt); int cur = rt;
for(int i = 17 ; i >= 0 ; --i){
bool flg = x >> i & 1; lst[cur = ch[cur][flg] = create(ch[cur][flg])] = t;
}
}
int qry(int rt , int x , int t){
int sum = 0;
for(int i = 17 ; i >= 0 ; --i){
bool flg = !(x >> i & 1);
if(lst[ch[rt][flg]] >= t){sum |= 1 << i; rt = ch[rt][flg];}
else rt = ch[rt][!flg];
}
return sum;
}
}
struct query{int L , R , val , id;};
struct modify{int plc , num;};
int N , M , Q , cnt , ans[_] , rt[_];
namespace segt{
vector < query > qry[_ << 2]; vector < modify > mdy[_ << 2];
#define mid ((l + r) >> 1)
#define lch (x << 1)
#define rch (x << 1 | 1)
void ins(int x , int l , int r , int L , int R , query q){
if(l >= L && r <= R) return qry[x].push_back(q);
if(mid >= L) ins(lch , l , mid , L , R , q);
if(mid < R) ins(rch , mid + 1 , r , L , R , q);
}
void ins(int x , int l , int r , int tar , modify m){
mdy[x].push_back(m); if(l == r) return;
mid >= tar ? ins(lch , l , mid , tar , m) : ins(rch , mid + 1 , r , tar , m);
}
void work(int x , int l , int r){
Trie::cnt = 0; int rt = 0 , pos = 0;
sort(mdy[x].begin() , mdy[x].end() , [&](modify A , modify B){return A.plc < B.plc;});
sort(qry[x].begin() , qry[x].end() , [&](query A , query B){return A.R < B.R;});
mdy[x].push_back((modify){(int)1e9 , 0});
for(auto t : mdy[x]){
while(pos < qry[x].size() && qry[x][pos].R < t.plc){
if(qry[x][pos].id == 168)
qry[x][pos].id = 168;
ans[qry[x][pos].id] = max(ans[qry[x][pos].id] , Trie::qry(rt , qry[x][pos].val , qry[x][pos].L));
++pos;
} Trie::ins(rt , t.plc , t.num);
}
if(l != r){work(lch , l , mid); work(rch , mid + 1 , r);}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
N = read(); M = read(); rt[0] = 0;
for(int i = 1 ; i <= N ; ++i) Trie::ins(rt[i] = rt[i - 1] , i , read());
for(int i = 1 ; i <= M ; ++i)
if(read()){
int L = read() , R = read() , x = read() , d = read() , id = ++Q;
if(d) segt::ins(1 , 0 , M , max(cnt - d + 1 , 0) , cnt , (query){L , R , x , id});
ans[id] = max(ans[id] , Trie::qry(rt[R] , x , L));
}
else{
int tms = ++cnt , plc = read() , val = read();
segt::ins(1 , 0 , M , tms , (modify){plc , val});
}
segt::work(1 , 0 , M); for(int i = 1 ; i <= Q ; ++i) printf("%d\n" , ans[i]);
return 0;
}