4568: [Scoi2016]幸运数字

题意:一颗带点权的树,求树上两点间异或值最大子集的异或值


显然要用线性基

可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合并起来就行了

复杂度\(O(nlogn60*60)\)

注意这是点权,特判x==y的情况,需要插入a[x]

还可以用点分治和树链剖分



我的代码好慢啊...但是很好写啊

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. using namespace std;
  7. typedef long long ll;
  8. #define pii pair<int, int>
  9. #define fir first
  10. #define sec second
  11. const int N=2e4+5;
  12. inline ll read() {
  13. char c=getchar(); ll x=0, f=1;
  14. while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
  15. while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
  16. return x*f;
  17. }
  18. int n, Q, u, v; ll a[N];
  19. struct edge{int v, ne;}e[N<<1];
  20. int cnt=1, h[N];
  21. inline void ins(int u, int v) {
  22. e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
  23. e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
  24. }
  25. namespace lb{
  26. struct meow {
  27. ll p[62];
  28. meow(){memset(p, 0, sizeof(p));}
  29. ll operator [](int x) {return p[x];}
  30. bool insert(ll val) {
  31. for(int i=60; i>=0; i--)
  32. if(val & (1LL<<i)) {
  33. if(p[i]) val ^= p[i];
  34. else {p[i]=val; break;}
  35. }
  36. return val>0;
  37. }
  38. void merge(meow &a) {
  39. for(int i=60; i>=0; i--) if(a[i]) insert(a[i]);
  40. }
  41. ll getmax() {
  42. ll ans=0;
  43. for(int i=60; i>=0; i--) ans = max(ans, ans^p[i]);
  44. return ans;
  45. }
  46. void print() {
  47. for(int i=60; i>=0; i--) if(p[i]) printf("p %d %lld\n",i,p[i]);
  48. puts("");
  49. }
  50. }b[N][17];
  51. }using lb::b; using lb::meow;
  52. int fa[N][17], deep[N];
  53. void dfs(int u) {
  54. for(int i=1; (1<<i)<=deep[u]; i++) {
  55. fa[u][i] = fa[ fa[u][i-1] ][i-1];
  56. b[u][i].merge(b[u][i-1]); b[u][i].merge(b[ fa[u][i-1] ][i-1]);
  57. }
  58. for(int i=h[u];i;i=e[i].ne)
  59. if(e[i].v != fa[u][0]) {
  60. fa[e[i].v][0]=u;
  61. deep[e[i].v]=deep[u]+1;
  62. b[e[i].v][0].insert(a[u]);
  63. dfs(e[i].v);
  64. }
  65. }
  66. meow lca(int x, int y) { //printf("lca %d %d\n",x,y);
  67. meow now;
  68. if(x==y) {now.insert(a[x]); return now;}
  69. if(deep[x]<deep[y]) swap(x, y);
  70. int bin=deep[x]-deep[y];
  71. for(int i=0; i<15; i++)
  72. if((1<<i)&bin) now.merge(b[x][i]), x=fa[x][i];
  73. if(x==y) return now;
  74. for(int i=14; i>=0; i--)
  75. if(fa[x][i] != fa[y][i]) now.merge(b[x][i]), now.merge(b[y][i]), x=fa[x][i], y=fa[y][i];
  76. now.merge(b[x][0]); now.insert(a[y]);
  77. //puts("now");now.print();
  78. return now;
  79. }
  80. ll Que(int x, int y) {
  81. return lca(x, y).getmax();
  82. }
  83. int main() {
  84. freopen("in","r",stdin);
  85. n=read(); Q=read();
  86. for(int i=1; i<=n; i++) a[i]=read(), b[i][0].insert(a[i]);
  87. for(int i=1; i<n; i++) ins(read(), read());
  88. dfs(1);
  89. //for(int i=1; i<=n; i++)
  90. // for(int j=0; (1<<j)<=deep[i]; j++) printf("hi %d %d %d\n",i,j,fa[i][j]), b[i][j].print();
  91. for(int i=1; i<=Q; i++) printf("%lld\n", Que(read(), read()));
  92. }

BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]的更多相关文章

  1. BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增

    [题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...

  2. 洛谷P3292 [SCOI2016]幸运数字 线性基+倍增

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

  3. P3292 [SCOI2016]幸运数字 [线性基+倍增]

    线性基+倍增 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define rep(i, x, y) for ( ...

  4. BZOJ4568: [Scoi2016]幸运数字(线性基 倍增)

    题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...

  5. BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)

    题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...

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

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

  7. P3292 [SCOI2016]幸运数字 线性基

    正解:线性基+倍增 解题报告: 先放下传送门QAQ 然后这题,其实没什么太大的技术含量,,,?就几个知识点套在一起,除了代码长以外没任何意义,主要因为想复习下线性基的题目所以还是写下,,, 随便写下思 ...

  8. BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...

  9. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

随机推荐

  1. hdu_4869(费马小定理+快速幂)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4869 Turn the pokers Time Limit: 2000/1000 MS (Java/O ...

  2. [国嵌攻略][143][LCD驱动程序分析]

    LCD驱动程序分析 LCD驱动程序代码在/drivers/video/s3c2410fb.c文件中,在该驱动的s3c2410fb_init中注册了平台驱动,该驱动的初始化代码在s3c24xxfc_pr ...

  3. EC+VO+SCOPE for ES3

    词法环境 词法作用域 词法作用域(lexcical scope).即JavaScript变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码. 词法环境 用于定义特定变量和函数标识 ...

  4. 炫酷线条动画--svg

    我们经常可以在一些页面看到看起来很酷的线条动画,有些可以用css实现,有些css就无能为力了,今天来研究另一种实现方式,svg 如果对svg是什么还不了解的话,可以先去看看svg的基础教程: 一般对于 ...

  5. Oracle_数据库表的约束

    Oracle_数据库表的约束 完整性约束分类 域完整性约束 (非空not null,检查check) 实体完整性约束 (唯一unique,主键primary key) 参照完整性约束 (外键forei ...

  6. git常见操作

    本地仓库关联远程仓库 新建本地目录scala git init 这样就新建了一个本地仓库 在远端如github上新建仓库scala 关联远程仓库 git remote add origin git@g ...

  7. CSS3 background-size图片自适应

    http://www.html5cn.com.cn/css3/2013-04-21/267.html background-size属性和background-origin属性.background- ...

  8. SQL语句order by两个字段同时排序。

    ORDER BY  后可加2个字段,用英文逗号隔开.理解:对两个字段都排序,并不是之排序其中的一个字段: f1用升序, f2降序,sql该这样写 ORDERBY  f1, f2  DESC 也可以这样 ...

  9. dede表前缀不定时,查询表#@__archives

    $query = "SELECT arc.*,tp.typedir,tp.typename,               tp.isdefault,tp.defaultname,tp.nam ...

  10. Linux日志轮循实现(shell)

    在Linux系统中,日志的使用非常频繁,那么对日志就需要一定策略的管理,包括存放目录的设计,log文件命名规则,历史log文件的存放,log目录的容量限制,另外还有日志轮循. 日志轮循就是,将过期的l ...