题意

考虑点分治,每次处理过重心的询问(即两点在重心的不同子树中)。

求出每个点到重心的线性基,之后对过重心的询问合并两点线性基求解。

code:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define pii pair<int,int>
  4. #define mkp make_pair
  5. #define fir first
  6. #define sec second
  7. typedef long long ll;
  8. const int maxn=20010;
  9. const int maxm=200010;
  10. const int inf=1e9;
  11. int n,m,cnt,root,maxsize=inf,trsize;
  12. int head[maxn],size[maxn],check[maxn];
  13. ll a[maxn],ans[maxm];
  14. bool vis[maxn];
  15. vector<pii>ve[maxn];
  16. struct edge{int to,nxt;}e[maxn<<1];
  17. struct Xord
  18. {
  19. ll d[65];
  20. Xord(){memset(d,0,sizeof(d));}
  21. inline void clear(){memset(d,0,sizeof(d));}
  22. inline void insert(ll x)
  23. {
  24. for(int i=61;~i;i--)
  25. {
  26. if(!(x&(1ll<<i)))continue;
  27. if(!d[i]){d[i]=x;return;}
  28. else x^=d[i];
  29. }
  30. }
  31. inline ll query()
  32. {
  33. ll res=0;
  34. for(int i=61;~i;i--)res=max(res,res^d[i]);
  35. return res;
  36. }
  37. }xord[maxn];
  38. inline void add(int u,int v)
  39. {
  40. e[++cnt].nxt=head[u];
  41. head[u]=cnt;
  42. e[cnt].to=v;
  43. }
  44. void getroot(int x,int fa)
  45. {
  46. size[x]=1;
  47. int maxx=0;
  48. for(int i=head[x];i;i=e[i].nxt)
  49. {
  50. int y=e[i].to;
  51. if(y==fa||vis[y])continue;
  52. getroot(y,x);size[x]+=size[y];
  53. maxx=max(maxx,size[y]);
  54. }
  55. maxx=max(maxx,trsize-size[x]);
  56. if(maxx<maxsize)maxsize=maxx,root=x;
  57. }
  58. void getxor(int x,int fa)
  59. {
  60. xord[x]=xord[fa];xord[x].insert(a[x]);
  61. for(unsigned int i=0;i<ve[x].size();i++)
  62. {
  63. int y=ve[x][i].fir;
  64. if(check[y]!=root)continue;
  65. Xord tmp=xord[x];
  66. for(int j=0;j<=60;j++)if(xord[y].d[j])tmp.insert(xord[y].d[j]);
  67. ans[ve[x][i].sec]=max(ans[ve[x][i].sec],tmp.query());
  68. }
  69. for(int i=head[x];i;i=e[i].nxt)
  70. {
  71. int y=e[i].to;
  72. if(y==fa||vis[y])continue;
  73. getxor(y,x);
  74. }
  75. }
  76. void mark(int x,int fa,int k)
  77. {
  78. check[x]=k;
  79. for(int i=head[x];i;i=e[i].nxt)
  80. {
  81. int y=e[i].to;
  82. if(y==fa||vis[y])continue;
  83. mark(y,x,k);
  84. }
  85. }
  86. void solve(int x)
  87. {
  88. //cerr<<x<<endl;
  89. vis[x]=1;check[x]=x;
  90. xord[x].clear();xord[x].insert(a[x]);
  91. for(int i=head[x];i;i=e[i].nxt)
  92. {
  93. int y=e[i].to;
  94. if(vis[y])continue;
  95. getxor(y,x);mark(y,x,x);
  96. }
  97. for(int i=head[x];i;i=e[i].nxt)
  98. {
  99. int y=e[i].to;
  100. if(vis[y])continue;
  101. maxsize=inf;trsize=size[y];getroot(y,0);
  102. solve(root);
  103. }
  104. }
  105. int main()
  106. {
  107. //freopen("test.in","r",stdin);
  108. //freopen("test.out","w",stdout);
  109. scanf("%d%d",&n,&m);
  110. for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
  111. for(int i=1;i<n;i++)
  112. {
  113. int u,v;scanf("%d%d",&u,&v);
  114. add(u,v),add(v,u);
  115. }
  116. for(int i=1;i<=m;i++)
  117. {
  118. int x,y;scanf("%d%d",&x,&y);
  119. if(x==y)ans[i]=a[x];
  120. else ve[x].push_back(mkp(y,i)),ve[y].push_back(mkp(x,i));
  121. }
  122. trsize=n;maxsize=inf;getroot(1,0);
  123. solve(root);
  124. for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
  125. return 0;
  126. }

luoguP3292 [SCOI2016]幸运数字(点分治做法)的更多相关文章

  1. luoguP3292 [SCOI2016]幸运数字(倍增做法)

    题意 线性基套上树上倍增即可,注意边界. code: #include<bits/stdc++.h> using namespace std; typedef long long ll; ...

  2. [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2131  Solved: 865[Submit][Statu ...

  3. BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]

    4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...

  4. [SCOI2016]幸运数字 树链剖分,线性基

    [SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...

  5. bzoj 4568: [Scoi2016]幸运数字

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 848  Solved: 336[Submit][Status ...

  6. [洛谷P3292] [SCOI2016]幸运数字

    洛谷题目链接:[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城 ...

  7. 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)

    4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...

  8. [BZOJ4568][Scoi2016]幸运数字 倍增+线性基

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1791  Solved: 685[Submit][Statu ...

  9. 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基

    [BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...

随机推荐

  1. 201871010106-丁宣元 《面向对象程序设计(java)》第一周学习总结

    丁宣元 <面向对象程序设计(java)>第一周学习总结 正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在 ...

  2. 201871010113-刘兴瑞《面向对象程序设计(java)》第十二周学习总结

    项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...

  3. spring cloud 2.x版本 Gateway自定义过滤器教程

    前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...

  4. Java实现编辑距离算法

    Java实现编辑距离算法 编辑距离,又称Levenshtein距离(莱文斯坦距离也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数,如果它们的距离越大,说明它 ...

  5. IT兄弟连 Java语法教程 数组 数组的初始化

    Java语言中数组必须先初始化,然后才可以使用.所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值. 这时有人会问,能不能只分配内存空间,不赋初始值呢?答案是肯定不行的,一旦为数组 ...

  6. C++入门到理解阶段二基础篇(4)——C++运算符

    目录 算术运算符(进行四则运算) 赋值运算符(表达式的值赋给变量) 比较运算符(表达是比较,返回一个真值或假值) 逻辑运算符(返回表格式的结果真或假) 位运算符 杂项运算符 C++ 中的运算符优先级 ...

  7. C++ const使用总结

    这里针对C++中const的一些一般用法进行一下简单的总结 一.定义常量 常量不可修改 : ; 与#define宏定义常量的区别:(1)const常量具有类型,编译器可以进行安全检查:#define宏 ...

  8. 投色子--html demo

    这是之前客户想要看的一个效果,不知道放在博客里面有没有关系,当做备份吧. <!DOCTYPE HTML> <html> <head> <meta charse ...

  9. Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: Eastmount PS:如有需要Python学习资料的小伙伴可以加 ...

  10. 通过SSH通道来访问MySQL

     许多时候当要使用Mysql时,会遇到如下情况: 1. 信息比较重要,希望通信被加密.2. 一些端口,比如3306端口,被路由器禁用. 对第一个问题的一个比较直接的解决办法就是更改mysql的代码,或 ...