# Mars store problem [FJOI2015] [line tree partition] [01Trie]

Posted by patheticsam on Tue, 11 Feb 2020 14:41:01 +0100

# thinking

It's very skillful to choose "time" of line tree divide and conquer. We can consider it from two aspects: time and position:

1. In addition to the special products of each store, the time dimension is modified as a single point, and the query is an interval
2. Location and modification are all single points, and inquiry is interval

It is also possible to divide and conquer with time dimension. Here, select location as the "time" of segment tree divide and conquer
This question has its own characteristics. It's interval query. We will split the query into O(nlogn)O(nlogn)O(nlogn) segments. What about the modification? It's all single point?
You can add all the lognlognlog points on the path to the value for a single modification by using the tag permanence

This ensures that the split nodes in the query [L,R][L,R][L,R] have valid values for self intervals (no matter whether the time is right or not)
Each node of the segment tree is a TrieTrieTrie
If only the exclusive or maximum value of query is 01Trie01Trie01Trie, but there is a time limit [L,R][L,R][L,R]
Consider sorting all operations by the right endpoint (in fact, the input order is already in order) before inserting
Then add maxumax? To the TrieTrieTrie node to indicate the latest insertion time in the subtree, and judge when asking

# Code

```#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstring>
#include<climits>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
//char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
bool f=0;LL x=0;char c=getchar();
while(c<'0'||'9'<c){if(c==EOF)exit(0);if(c=='-')f=1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return !f?x:-x;
}
#define lch (u<<1)
#define rch (u<<1|1)
#define MAXN 100000
#define INF 0x3f3f3f3f
struct node{
int type,tl,tr,pl,pr,val,id;
friend bool operator < (node a,node b){return a.tr==b.tr?a.type<b.type:a.tr<b.tr;}
}Q[MAXN+5];
int qcnt,ans[MAXN+5];
vector<node> tree[5*MAXN+5];
void Insert_Seg(int u,int L,int R,node p){
if(p.type==0)
tree[u].push_back(p);
if(p.pl<=L&&R<=p.pr){
if(p.type==1)
tree[u].push_back(p);
return ;
}
int Mid=(L+R)>>1;
if(p.pl<=Mid)
Insert_Seg(lch,L,Mid,p);
if(Mid+1<=p.pr)
Insert_Seg(rch,Mid+1,R,p);
return ;
}
int ncnt,Root,ch[30*MAXN+5][2],Max[30*MAXN+5];
void Init(){
for(int i=1;i<=ncnt;i++)
ch[i][0]=ch[i][1]=Max[i]=0;
ncnt=Root=1;
return ;
}
void Insert(int pos,int val){
int u=Root;
for(int i=19;i>=0;i--){
int t=(val>>i)&1;
if(!ch[u][t])
ch[u][t]=++ncnt;
u=ch[u][t];
Max[u]=max(Max[u],pos);
}
return ;
}
int Query(int pos,int val){
int u=Root,ret=0;
for(int i=19;i>=0;i--){
int t=((val>>i)&1)^1;
if(ch[u][t]&&pos<=Max[ch[u][t]])
ret+=(1<<i),u=ch[u][t];
else u=ch[u][t^1];
}
return ret;
}
void DFS(int u,int L,int R){
Init();
for(int i=0;i<(int)tree[u].size();i++){
node p=tree[u][i];
if(p.id==1){
i++;
i--;
}
if(p.type==0)
Insert(p.tr,p.val);
else
ans[p.id]=max(ans[p.id],Query(p.tl,p.val));
}
if(L==R)
return ;
int Mid=(L+R)>>1;
DFS(lch,L,Mid),DFS(rch,Mid+1,R);
return ;
}
int main(){
for(int i=1;i<=n;i++)
for(int i=1;i<=m;i++){
node p;
if(opt==0){
day++;
p=(node){0,day,day,s,s,v,0};
}
else{
p=(node){1,tl,tr,pl,pr,x,++cnt};
}
Insert_Seg(1,1,n,p);
}
DFS(1,1,n);
for(int i=1;i<=cnt;i++)
printf("%d\n",ans[i]);
return 0;
}

```

# Reflection

For the segment tree divide and conquer itself can ensure the "time" order, then it is a good way to try to order other parameters after offline sorting

Published 115 original articles, won praise 191, visited 20000+