由于是统计树上某个区间的值,因此就是树上莫队了。
套个树上莫队的模板先。。。
对树上的区间进行排序,然后更新的时候判断一下更新的节点是奇还是偶,放进cnt数组里面。然后问题来了。
查询的是对cnt数组的一个区间进行查询,那么这里就需要用到树状数组去二分了。
这样在修改的时候就多了一个log,这样就T了。
所以不能对修改做任何扩展,只能修改查询部分。
继续使用分块思想。对cnt数组去分组。然后查询的时候一组一组去查询,如果组内有数据,就直接暴力返回结果。
一共有sqrt(n)个组,组内查询时间sqrt(n),那么总时间就是sqrt(n)+sqrt(n)了。
这样总时间也是q*sqrt(n)了。
int block_size;
struct query{
int l,r,id;
int u,v;
int block;
int r_block;
bool operator<(const query &q) const{
if(block != q.block) return block<q.block;
return r_block<q.r_block;
}
};
vector<int> g[N];
stack<int> st;
int blk,idx;
int block_num[N];
int sz[N],hs[N],dp[N],dfn[N],fa[N],top[N];
int ans[N],sum[N],num[N];
int c[N];
int n;
void dfs1(int t, int f){
sz[t] = 1;
fa[t] = f;
hs[t] = 0;
dp[t] = dp[f]+1;
dfn[t] = idx++;
st.push(t);
int ss = st.size();
for(int u:g[t]){
if(u==f)continue;
dfs1(u,t);
sz[t] += sz[u];
if(sz[u] > sz[hs[t]]) hs[t] = u;
if(st.size() - ss >=block_size){
while(st.size() >ss){
block_num[st.top()]=blk;
st.pop();
}
blk++;
}
}
if(t==1){
while(!st.empty()){
block_num[st.top()]=blk;
st.pop();
}
blk++;
}
}
void dfs2(int t, int f){
top[t] = f;
if(!hs[t])return;
dfs2(hs[t],f);
for(int u : g[t]){
if(u==fa[t] || u == hs[t])continue;
dfs2(u,u);
}
}
int lca(int u, int v){
if(dp[u]<dp[v])swap(u,v);
while(top[u]!=top[v]) {
if(dp[top[u]] > dp[top[v]]) u = fa[top[u]];
else v = fa[top[v]];
}
return dp[u]<dp[v]? u:v;
}
int get_ans(int l, int r){
int bl = l/block_size;
int br = r/block_size;
for(int i = bl; i<=br; ++i){
if(sum[i]==0)continue;
int st = i * block_size;
int ed = (i+1)*block_size-1;
for(int i = max(st,l); i<=min(r,ed); ++i){
if(num[i]) return i;
}
}
return -1;
}
void change(int u){
if(num[c[u]]==0){
sum[c[u]/block_size]++;
}
else {
sum[c[u]/block_size]--;
}
num[c[u]]^=1;
}
int l = 0, r = 0;
void move(int u, int v){
if(dp[u]<dp[v]) swap(u,v);
while(dp[u]!=dp[v]){
change(u);
u = fa[u];
}
while(u!=v){
change(u); change(v);
u = fa[u]; v = fa[v];
}
}
int main(){
int Q;
sf("%d%d",&n,&Q);
block_size = pow(n,0.6);
for(int i = 1; i <= n; ++i){
sf("%d",&c[i]);
}
for(int i= 0; i<n-1; ++i){
int u,v;
sf("%d%d",&u,&v);
g[u].pb(v);
g[v].pb(u);
}
dfs1(1,1);
dfs2(1,1);
vector<query> q;
map<pair<int,int>, vector<query>> tmp_ans;
for(int i = 0; i < Q; ++i){
query qy;
sf("%d%d%d%d",&qy.u,&qy.v,&qy.l,&qy.r);
if(dfn[qy.u]>dfn[qy.v]){
swap(qy.u,qy.v);
}
qy.block = block_num[qy.u];
qy.r_block = block_num[qy.v];
qy.id = i;
q.pb(qy);
}
sort(q.begin(), q.end());
int u = 1, v = 1;
change(lca(u,v));
l = 0, r = 0;
deque<int> cq;
for(int i = 0; i < q.size();++i){
int f = lca(u,v);
change(f);
if(u!=q[i].u){
move(u,q[i].u);
u = q[i].u;
}
if(v!=q[i].v){
move(v,q[i].v);
v = q[i].v;
}
f = lca(u,v);
change(f);
ans[q[i].id] = get_ans(q[i].l, q[i].r);
}
for(int i = 0; i < q.size();++i){
printf("%d\n",ans[i]);
}
}