先考虑判定是否有解,注意到无解即每一个数都出现偶数次,根据异或的性质,只需要随机$V_{i}$,假设$u$到$v$路径上所有节点构成集合$S$,若$\bigoplus_{x\in S,l\le a_{x}\le r}V_{a_{x}}=0$即无解

考虑如何快速计算上述值,根据异或的自反性,对其差分,也即统计一个节点到根路径上的权值异或,建立线段树,并在其父亲的基础上可持久化即可

更进一步的,在这个线段树上二分即可得到答案(即先判定每一段是否为0,再在其中二分)

时间复杂度为$o(n\log n)$,即可通过

下面来分析概率,假设$V_{i}$的随机范围为$[0,V)$(其中$V$为2的幂次),考虑答案错误的概率——

考虑一次询问中,求得异或为0但实际存在出现奇数次权值的概率,即$\frac{1}{V}$

总共询问$o(q\log n)$次,可以估计概率为$\frac{q\log n}{V}$,当$V\sim 2^{64}$即足够高

(另外注意随机时,如果是选择若干个数相乘,需要判定最终结果不为0)

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 300005
4 #define ull unsigned long long
5 #define mid (l+r>>1)
6 struct Edge{
7 int nex,to;
8 }edge[N<<1];
9 int V,E,n,q,x,y,l,r,z,zz,head[N],dep[N],rt[N],a[N],f[N][21],ls[N*20],rs[N*20];
10 ull R[N],sum[N*20];
11 int New(int k){
12 sum[++V]=sum[k];
13 ls[V]=ls[k];
14 rs[V]=rs[k];
15 return V;
16 }
17 void add(int x,int y){
18 edge[E].nex=head[x];
19 edge[E].to=y;
20 head[x]=E++;
21 }
22 int lca(int x,int y){
23 if (dep[x]<dep[y])swap(x,y);
24 for(int i=20;i>=0;i--)
25 if (dep[f[x][i]]>=dep[y])x=f[x][i];
26 if (x==y)return x;
27 for(int i=20;i>=0;i--)
28 if (f[x][i]!=f[y][i]){
29 x=f[x][i];
30 y=f[y][i];
31 }
32 return f[x][0];
33 }
34 void update(int &k,int l,int r,int x,ull y){
35 k=New(k);
36 sum[k]^=y;
37 if (l==r)return;
38 if (x<=mid)update(ls[k],l,mid,x,y);
39 else update(rs[k],mid+1,r,x,y);
40 }
41 int query(int k1,int k2,int k3,int k4,int l,int r,int x,int y){
42 if ((l>y)||(x>r))return -1;
43 if ((x<=l)&&(r<=y)){
44 if (!(sum[k1]^sum[k2]^sum[k3]^sum[k4]))return -1;
45 }
46 if (l==r)return l;
47 int ans=query(ls[k1],ls[k2],ls[k3],ls[k4],l,mid,x,y);
48 if (ans>=0)return ans;
49 return query(rs[k1],rs[k2],rs[k3],rs[k4],mid+1,r,x,y);
50 }
51 void dfs(int k,int fa,int s){
52 dep[k]=s;
53 f[k][0]=fa;
54 for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
55 rt[k]=rt[fa];
56 update(rt[k],1,n,a[k],R[a[k]]);
57 for(int i=head[k];i!=-1;i=edge[i].nex)
58 if (edge[i].to!=fa)dfs(edge[i].to,k,s+1);
59 }
60 int main(){
61 srand(time(0));
62 scanf("%d%d",&n,&q);
63 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
64 for(int i=1;i<=n;i++)
65 while (!R[i])R[i]=(ull)rand()*(ull)rand()*(ull)rand()*(ull)rand()*(ull)rand();
66 memset(head,-1,sizeof(head));
67 for(int i=1;i<n;i++){
68 scanf("%d%d",&x,&y);
69 add(x,y);
70 add(y,x);
71 }
72 dfs(1,0,1);
73 for(int i=1;i<=q;i++){
74 scanf("%d%d%d%d",&x,&y,&l,&r);
75 z=lca(x,y),zz=f[z][0];
76 printf("%d\n",query(rt[x],rt[y],rt[z],rt[zz],1,n,l,r));
77 }
78 }

最新文章

  1. Java面试(1)-- Java逻辑运算符
  2. SGA(System Global Area)
  3. ros下多机器人系统(1)
  4. iOS中响应者链条-触摸事件
  5. 2015GitWebRTC编译实录17-audio_processing_neon编译问题解决
  6. loadrunner 如何做关联
  7. 论文阅读之 A Convex Optimization Framework for Active Learning
  8. Java8新特性【转】
  9. 【C++】指针数组和数组指针
  10. 转:YUV RGB 常见视频格式解析
  11. 非常好的Demo网站
  12. bzoj4038: 医疗援助
  13. 设置标题小图标ico
  14. DL4NLP——词表示模型(一)表示学习;syntagmatic与paradigmatic两类模型;基于矩阵的LSA和GloVe
  15. SSH框架之-hibernate 三种状态的转换
  16. kodi18.1设置中文的方法
  17. 自学Linux Shell18.3-sed实用工具
  18. 站点防火墙api,增加黑名单IP接口,增加用post,修改用put,php案例
  19. [Java123] JDBC and Multi-Threading 多线程编程学习笔记
  20. 淘宝免费ip地址查询导致服务堵死的坑

热门文章

  1. Linux安装配置Java
  2. WPF实现聚光灯效果
  3. 查询windows日志
  4. 基于Hyperledger Fabric实现ERC721
  5. 前段---css
  6. iOS自动化之WDA(WebDriverAgent)安装
  7. Spark分区器浅析
  8. SpringCloud微服务实战——搭建企业级开发框架(四):集成SpringCloud+SpringBoot
  9. 【UE4 C++】绘制函数 Debug drawing functions
  10. Sequence Model-week1编程题1(一步步实现RNN与LSTM)