先考虑NOI2014的水题,显然从高位到低位贪心,算一下该位取0和1分别得到什么即可。

  加强这个水题,变成询问区间。那么线段树维护该位取0和1从左到右和从右到左走完这个节点表示的区间会变成什么即可,也滋磁修改了。

  然后上树,显然树剖即可。非常惨的变成了O(nklog2n)。压一下位就不惨了,变成O(n(k+log2n))。

  树剖lca都能写挂调一天,不会熟练剖分,退役了。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. #define ll unsigned long long
  9. #define N 100010
  10. char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
  11. int gcd(int n,int m){return m==?n:gcd(m,n%m);}
  12. ll read()
  13. {
  14. ll x=;char c=getchar();
  15. while (c<''||c>'') c=getchar();
  16. while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
  17. return x;
  18. }
  19. ll b[N],gor[N<<][],gol[N<<][],inf,I;
  20. int n,m,k,a[N],p[N],t,cnt;
  21. int id[N],dfn[N],top[N],fa[N],son[N],size[N],deep[N];
  22. int L[N<<],R[N<<];
  23. struct data{int to,nxt;
  24. }edge[N<<];
  25. struct data2{ll x,y;};
  26. void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
  27. void dfs(int k)
  28. {
  29. size[k]=;
  30. for (int i=p[k];i;i=edge[i].nxt)
  31. if (edge[i].to!=fa[k])
  32. {
  33. fa[edge[i].to]=k;
  34. deep[edge[i].to]=deep[k]+;
  35. dfs(edge[i].to);
  36. size[k]+=size[edge[i].to];
  37. if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to;
  38. }
  39. }
  40. void dfs2(int k,int from)
  41. {
  42. top[k]=from;dfn[k]=++cnt;id[cnt]=k;
  43. if (son[k]) dfs2(son[k],from);
  44. for (int i=p[k];i;i=edge[i].nxt)
  45. if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) dfs2(edge[i].to,edge[i].to);
  46. }
  47. ll trans1(ll x,int op,ll y){if (op==) return x&y;if (op==) return x|y;return x^y;}
  48. ll trans(ll x,ll t0,ll t1){return (x&t1)|((~x)&t0);}
  49. void up(int k)
  50. {
  51. gor[k][]=trans(gor[k<<][],gor[k<<|][],gor[k<<|][]);
  52. gor[k][]=trans(gor[k<<][],gor[k<<|][],gor[k<<|][]);
  53. gol[k][]=trans(gol[k<<|][],gol[k<<][],gol[k<<][]);
  54. gol[k][]=trans(gol[k<<|][],gol[k<<][],gol[k<<][]);
  55. }
  56. void build(int k,int l,int r)
  57. {
  58. L[k]=l,R[k]=r;
  59. if (l==r) {gol[k][]=gor[k][]=trans1(,a[id[l]],b[id[l]]);gol[k][]=gor[k][]=trans1(inf,a[id[l]],b[id[l]]);return;}
  60. int mid=l+r>>;
  61. build(k<<,l,mid);
  62. build(k<<|,mid+,r);
  63. up(k);
  64. }
  65. void modify(int k,int x,int op,ll y)
  66. {
  67. if (L[k]==R[k]) {gol[k][]=gor[k][]=trans1(,op,y);gol[k][]=gor[k][]=trans1(inf,op,y);return;}
  68. int mid=L[k]+R[k]>>;
  69. if (x<=mid) modify(k<<,x,op,y);
  70. else modify(k<<|,x,op,y);
  71. up(k);
  72. }
  73. data2 queryl(int k,int l,int r)
  74. {
  75. if (L[k]==l&&R[k]==r) return (data2){gol[k][],gol[k][]};
  76. int mid=L[k]+R[k]>>;
  77. if (r<=mid) return queryl(k<<,l,r);
  78. else if (l>mid) return queryl(k<<|,l,r);
  79. else
  80. {
  81. data2 x=queryl(k<<|,mid+,r),y=queryl(k<<,l,mid);
  82. return (data2){trans(x.x,y.x,y.y),trans(x.y,y.x,y.y)};
  83. }
  84. }
  85. data2 queryr(int k,int l,int r)
  86. {
  87. if (L[k]==l&&R[k]==r) return (data2){gor[k][],gor[k][]};
  88. int mid=L[k]+R[k]>>;
  89. if (r<=mid) return queryr(k<<,l,r);
  90. else if (l>mid) return queryr(k<<|,l,r);
  91. else
  92. {
  93. data2 x=queryr(k<<,l,mid),y=queryr(k<<|,mid+,r);
  94. return (data2){trans(x.x,y.x,y.y),trans(x.y,y.x,y.y)};
  95. }
  96. }
  97. void solve(ll &t0,ll &t1,int x,int lca)
  98. {
  99. if (top[x]==top[lca])
  100. {
  101. data2 t=queryr(,dfn[lca],dfn[x]);
  102. t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
  103. return;
  104. }
  105. solve(t0,t1,fa[top[x]],lca);
  106. data2 t=queryr(,dfn[top[x]],dfn[x]);
  107. t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
  108. }
  109. ll jump_query(int x,int y,ll z)
  110. {
  111. ll t0=,t1=inf;data2 t;int lca=,P=x,Q=y;
  112. while (top[P]!=top[Q])
  113. {
  114. if (deep[top[P]]<deep[top[Q]]) swap(P,Q);
  115. P=fa[top[P]];
  116. }
  117. if (deep[P]<deep[Q]) swap(P,Q);
  118. lca=Q;
  119. while (top[x]!=top[lca])
  120. {
  121. t=queryl(,dfn[top[x]],dfn[x]);
  122. t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
  123. x=fa[top[x]];
  124. }
  125. if (lca!=x)
  126. {
  127. for (int i=p[lca];i;i=edge[i].nxt)
  128. if (dfn[edge[i].to]>dfn[lca]&&dfn[edge[i].to]<=dfn[x]) {t=queryl(,dfn[edge[i].to],dfn[x]);break;}
  129. t0=trans(t0,t.x,t.y),t1=trans(t1,t.x,t.y);
  130. }
  131. solve(t0,t1,y,lca);
  132. ll s=,c=;
  133. for (int i=k-;~i;i--)
  134. if (t0&(I<<i)) s+=I<<i;
  135. else if ((t1&(I<<i))&&c+(I<<i)<=z) c+=I<<i,s+=I<<i;
  136. return s;
  137. }
  138. int main()
  139. {
  140. #ifndef ONLINE_JUDGE
  141. freopen("bzoj4811.in","r",stdin);
  142. freopen("bzoj4811.out","w",stdout);
  143. const char LL[]="%I64d\n";
  144. #else
  145. const char LL[]="%lld\n";
  146. #endif
  147. n=read(),m=read(),k=read();inf=I=;for (int i=;i<=k;i++) inf<<=;inf--;
  148. for (int i=;i<=n;i++) a[i]=read(),b[i]=read();
  149. for (int i=;i<n;i++)
  150. {
  151. int x=read(),y=read();
  152. addedge(x,y),addedge(y,x);
  153. }
  154. dfs();
  155. dfs2(,);
  156. build(,,n);
  157. while (m--)
  158. {
  159. int op=read(),x=read(),y=read();ll z=read();
  160. if (op==) printf("%llu\n",jump_query(x,y,z));
  161. else modify(,dfn[x],y,z);
  162. }
  163. return ;
  164. }

BZOJ4811 Ynoi2017由乃的OJ(树链剖分+线段树)的更多相关文章

  1. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

  2. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  3. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  4. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  5. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  6. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  7. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  8. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  9. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  10. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

随机推荐

  1. WPF 应用程序资源、内容和数据文件

    MSDN相关介绍: http://msdn.microsoft.com/zh-cn/library/aa970494(v=vs.100).aspx 内容文件(Content Files)内容文件简单的 ...

  2. Java:二进制(原码、反码、补码)与位运算

    一.二进制(原码.反码.补码) 二进制的最高位是符号位(“0”代表正数,“1”代表负数): Java中没有无符号数: 计算机以整数的补码进行运算: 1.  原码:将一个整数转换成二进制表示 以 int ...

  3. 解决replace格式替换后光标定位问题

    场景:格式化银行卡444格式 手机号344格式 身份证号684格式 校验数据格式,replace后光标定位错乱 或光标一直定位在最后 解决,只针对input,代码用的vue: 获取光标位置: getC ...

  4. 代码重复率检查工具jsinspect

    检查重复代码,去掉冗余代码. 安装: npm install -g jsinspect 用法:jsinspect [options] <paths ...> 检测复制粘贴和结构类似的Jav ...

  5. 「专题训练」Air Raid(HDU-1151)

    题目 在一个城市里有\(n\)个地点和\(k\)条道路,道路是无环的(也就是说一定可以二分染色--回路长度为偶数0),现在伞兵需要去n个地点视察,只能沿着路的方向走,问最少需要多少伞兵. 分析 这是什 ...

  6. 通过 Python_Faker 生成测试数据

    通过 Python_Faker 生成测试数据 一.介绍 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,你不可能通过手工来生成(最傻的方法)可能 ...

  7. C#冒泡排序法及优化

    冒泡排序法及优化: static void Main(string[] args) { , , , , , }; ; //冒泡排序法 ; i < sums.Length - ; i++) //总 ...

  8. MVC数据的注册及验证简单总结

    一.注解 注解是一种通用机制,可以用来向框架注入元数据,同时,框架不只驱动元数据的验证,还可以在生成显示和编辑模型的HTML标记时使用元数据. 二.验证注册的使用 1.Require:属性为Null或 ...

  9. [Clr via C#读书笔记]Cp10属性

    Cp10属性 属性的本质就是方法,只是看起来像字段罢了: 无参属性 就是一般属性: 字段一般要private,然后通过设置访问方法-访问器来访问:属性是方法语法变种:getset不一定要访问支持字段: ...

  10. Hexo 博客 之 腾讯云部署过程

    写在前面 Hexo 博客搭好了有差不多两周时间了,这期间走了很多弯路,跳了很多坑.一些坑自己 bing 到了答案,找到了解决方法,一些坑则是自己摸索出来的解决方法.现在准备写几篇关于搭建流程.搭建过程 ...