吐槽
睡起来写道模板清醒一下
貌似有两个log的树剖写法,还有一个log的Trie树的差分做法(类似于count on a tree),然后一个log的要把两个询问分开写,一个dfs序一个差分,然后我就写了好写的树剖写法
以及为啥出题人这么喜欢把序列问题放到树上啊。。。
可持久化Tried树模板难度,懒得写思路
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 100100;
struct Node{
int son[2],sz;
}Trie[MAXN*40];
const int MAXlen=30;
int u[MAXN<<1],v[MAXN<<1],w[MAXN],nxt[MAXN<<1],root[MAXN],dep[MAXN],fir[MAXN],id[MAXN],top[MAXN],sz[MAXN],heason[MAXN],fa[MAXN],cnt,dfs_clock,w_p[MAXN],n,m,Nodecnt;
void addedge(int ui,int vi){
++cnt;
u[cnt]=ui;
v[cnt]=vi;
nxt[cnt]=fir[ui];
fir[ui]=cnt;
}
void dfs1(int u,int f){
sz[u]=1;
fa[u]=f;
dep[u]=dep[f]+1;
for(int i=fir[u];i;i=nxt[i]){
if(v[i]==f)
continue;
dfs1(v[i],u);
sz[u]+=sz[v[i]];
if(heason[u]==0||sz[heason[u]]<sz[v[i]])
heason[u]=v[i];
}
}
void dfs2(int u,int topf){
id[u]=++dfs_clock;
w[id[u]]=w_p[u];
top[u]=topf;
if(!heason[u])
return;
dfs2(heason[u],topf);
for(int i=fir[u];i;i=nxt[i]){
if(v[i]==fa[u]||v[i]==heason[u])
continue;
dfs2(v[i],v[i]);
}
}
void insert(int d,int val,int &o){
Trie[++Nodecnt]=Trie[o];
o=Nodecnt;
Trie[o].sz++;
if(d>=0)
insert(d-1,val,Trie[o].son[(val>>d)&1]);
}
int query(int lroot,int rroot,int val,int d){
if(d<0)
return 0;
int flag=(val>>d)&1;
if(Trie[rroot].son[!flag]>Trie[lroot].son[!flag])
return (1<<d)+query(Trie[lroot].son[!flag],Trie[rroot].son[!flag],val,d-1);
else
return query(Trie[lroot].son[flag],Trie[rroot].son[flag],val,d-1);
}
void build(void){
for(int i=1;i<=dfs_clock;i++){
root[i]=root[i-1];
insert(MAXlen,w[i],root[i]);
}
}
int query(int x,int y,int c){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])
swap(x,y);
ans=max(ans,query(root[id[top[x]]-1],root[id[x]],c,MAXlen));
x=fa[top[x]];
}
if(dep[x]>dep[y])
swap(x,y);
ans=max(ans,query(root[id[x]-1],root[id[y]],c,MAXlen));
return ans;
}
int query(int x,int c){
return query(root[id[x]-1],root[id[x]+sz[x]-1],c,MAXlen);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&w_p[i]);
for(int i=1;i<n;i++){
int a,b;
scanf("%d %d",&a,&b);
addedge(a,b);
addedge(b,a);
}
dfs1(1,0);
dfs2(1,1);
build();
for(int i=1;i<=m;i++){
int opt,x,y,z;
scanf("%d %d %d",&opt,&x,&y);
if(opt==1){
printf("%d
",query(x,y));
}
else{
scanf("%d",&z);
printf("%d
",query(x,y,z));
}
}
return 0;
}